Squashed commit of the following:

commit afb25f406b
Author: Christian Bayer <chrbayer84@googlemail.com>
Date:   Mon Sep 5 21:45:16 2022 -0400

    WIP german translation

commit 3abbf5cd5f
Author: Christian Bayer <chrbayer84@googlemail.com>
Date:   Sat Sep 3 15:06:47 2022 -0400

    WIP german translation and some programmatic translation from CR

commit 4c8fcc656b
Author: Matthew Chambers <nr0q@gridtracker.org>
Date:   Mon Aug 15 22:14:16 2022 -0500

    progress so far, fixed what got broke in CR and fixed being able to close and reopen CR. still need to get i18n figured out

commit 78aaaed2ad
Author: Matthew Chambers <nr0q@gridtracker.org>
Date:   Mon Aug 15 20:19:09 2022 -0500

    one step forward, 2 steps backwards

commit 903319452b
Author: Christian Bayer <chrbayer84@googlemail.com>
Date:   Mon Aug 15 23:23:51 2022 +0200

    WIP translating strings in js: roster.js

commit 934f619af6
Author: Matthew Chambers <nr0q@gridtracker.org>
Date:   Mon Aug 15 00:06:13 2022 -0500

    add JA because may have a JA contributor

commit 8c7bd091ac
Author: Matthew Chambers <nr0q@gridtracker.org>
Date:   Sun Aug 14 23:41:29 2022 -0500

    all JS files have been passed through, may need another pass through all files though

commit 835892b70b
Author: Matthew Chambers <nr0q@gridtracker.org>
Date:   Sun Aug 14 20:03:18 2022 -0500

    Finished gt.js tags

commit 404dd1a247
Author: Matthew Chambers <nr0q@gridtracker.org>
Date:   Sun Aug 14 18:10:34 2022 -0500

    progress so far (up to line 9871 in gt.js)

commit c59473f898
Author: Matthew Chambers <nr0q@gridtracker.org>
Date:   Sun Aug 14 12:43:01 2022 -0500

    add comment between adif and alerts js files in en.json

commit 80cb9d5178
Author: Matthew Chambers <nr0q@gridtracker.org>
Date:   Sun Aug 14 12:42:27 2022 -0500

    Fix Chinese label to a more proper one

commit 08a00eeae8
Author: Christian Bayer <chrbayer84@googlemail.com>
Date:   Sun Aug 14 16:54:32 2022 +0200

    moved scripts

commit 8c9569b1c5
Author: Christian Bayer <chrbayer84@googlemail.com>
Date:   Sun Aug 14 16:51:10 2022 +0200

    started german translation

commit b857ecf91e
Author: Matthew Chambers <nr0q@gridtracker.org>
Date:   Sun Aug 14 01:37:39 2022 -0500

    tags for adif and alerts js files

commit 9c328de842
Author: Christian Bayer <chrbayer84@googlemail.com>
Date:   Sun Aug 14 08:23:51 2022 +0200

    fixed cn.json additonal keys

commit 7bc459195f
Author: Christian Bayer <chrbayer84@googlemail.com>
Date:   Sun Aug 14 08:20:22 2022 +0200

    Revert "fixed CN.json"

    This reverts commit f2f71c94db.

commit 236bea23bd
Author: Matthew Chambers <nr0q@gridtracker.org>
Date:   Sat Aug 13 19:02:49 2022 -0500

    cleanup and lint

commit a78d32ed1b
Author: Matthew Chambers <nr0q@gridtracker.org>
Date:   Sat Aug 13 19:01:47 2022 -0500

    THis works!

commit edc0d40256
Author: Matthew Chambers <nr0q@gridtracker.org>
Date:   Sat Aug 13 18:17:15 2022 -0500

    more tweaks trying to make it work

commit f2f71c94db
Author: Matthew Chambers <nr0q@gridtracker.org>
Date:   Sat Aug 13 17:09:39 2022 -0500

    fixed CN.json

commit 9b90cf4b14
Author: Matthew Chambers <nr0q@gridtracker.org>
Date:   Sat Aug 13 16:33:09 2022 -0500

    language change so far

commit dd60fc5012
Author: Christian Bayer <chrbayer84@googlemail.com>
Date:   Sat Aug 13 22:19:25 2022 +0200

    added missing keys to cn.json

commit fc5e25c81a
Author: Matthew Chambers <nr0q@gridtracker.org>
Date:   Sat Aug 13 15:18:54 2022 -0500

    Fixed linting`

commit 485adc6da1
Author: Matthew Chambers <nr0q@gridtracker.org>
Date:   Sat Aug 13 14:57:30 2022 -0500

    slight cleanup

commit dada794ccd
Author: Christian Bayer <chrbayer84@googlemail.com>
Date:   Sat Aug 13 21:55:55 2022 +0200

    fixed cn json

commit 82809c0458
Author: Matthew Chambers <nr0q@gridtracker.org>
Date:   Sat Aug 13 14:45:21 2022 -0500

    added dropdown for language in settings

commit 3159040b51
Author: Christian Bayer <chrbayer84@googlemail.com>
Date:   Fri Aug 12 22:29:51 2022 +0200

    added raw output of the i18n extractor. needs cleanup

commit 8f31e9e757
Author: Christian Bayer <chrbayer84@googlemail.com>
Date:   Thu Aug 11 22:29:12 2022 +0200

    added i18n generator script based off of a patch file

commit de81e35754
Author: Christian Bayer <chrbayer84@googlemail.com>
Date:   Mon Aug 8 22:20:47 2022 +0200

    added cascading install for nested package.json

commit bf7ecfeb4f
Author: Christian Bayer <chrbayer84@googlemail.com>
Date:   Mon Aug 8 22:11:18 2022 +0200

    added pota key

commit e14bca8172
Merge: f8c7232 91145aa
Author: Matthew Chambers <nr0q@gridtracker.org>
Date:   Sun Aug 7 18:39:40 2022 +0000

    Merge branch 'master' into 'cbayer-i18n'

    Master

    See merge request gridtracker.org/gridtracker!182

    If this is changing anything in the UI or operational behavior, please prepare to update the wiki!

commit f8c7232c38
Author: Matthew Chambers <nr0q@gridtracker.org>
Date:   Sun Aug 7 12:54:04 2022 -0500

    add jquery to npm depends

commit 734e972d9e
Author: Matthew Chambers <nr0q@gridtracker.org>
Date:   Sun Aug 7 12:53:24 2022 -0500

    wip, i18n debugging

commit 013d9c8ebf
Author: Christian Bayer <chrbayer84@googlemail.com>
Date:   Sun Aug 7 10:34:19 2022 +0200

    small fixes

commit 8da135bb6d
Merge: 0183434 c1f7f1b
Author: Christian Bayer <chrbayer84@googlemail.com>
Date:   Sat Aug 6 22:39:24 2022 +0200

    Merge branch 'master' into cbayer-i18n

commit 0183434bba
Author: Christian Bayer <chrbayer84@googlemail.com>
Date:   Sat Aug 6 22:27:35 2022 +0200

    removed banana import

commit 670001a6db
Merge: c120df0 236ff10
Author: Matthew Chambers <nr0q@gridtracker.org>
Date:   Tue May 17 18:38:11 2022 -0500

    Merge branch 'master' into cbayer-i18n

commit c120df0e3b
Author: Matthew Chambers <nr0q@gridtracker.org>
Date:   Thu Dec 16 15:15:21 2021 -0600

    the linter lints

commit 2243beddb2
Author: Matthew Chambers <nr0q@gridtracker.org>
Date:   Thu Dec 16 14:39:00 2021 -0600

    mostly finished with gridtracker.html file's i18n

commit 33d69c9501
Author: Matthew Chambers <nr0q@gridtracker.org>
Date:   Thu Dec 16 14:36:34 2021 -0600

    add functions to get acks json off website and overwrite file

commit 98170dce4f
Author: Matthew Chambers <nr0q@gridtracker.org>
Date:   Thu Dec 16 15:02:46 2021 -0600

    Initial workup for LoTW throttling & diff fetching

commit 655c041663
Author: Matthew Chambers <nr0q@gridtracker.org>
Date:   Thu Dec 16 14:31:19 2021 -0600

    WIP banana i18n

commit 26495c1f14
Author: Matthew Chambers <nr0q@gridtracker.org>
Date:   Wed Dec 15 11:52:08 2021 -0600

    update rpm spec 1.21.1212

commit e00269304d
Author: Matthew Chambers <nr0q@gridtracker.org>
Date:   Thu Dec 16 14:47:50 2021 -0600

    Trigger COPR and AUR repos and build .deb

commit 2b2e660108
Author: Matthew Chambers <nr0q@gridtracker.org>
Date:   Wed Dec 15 11:46:41 2021 -0600

    updated changelog / release notes

commit 0265f75fd8
Author: Matthew Chambers <nr0q@gridtracker.org>
Date:   Mon Dec 13 20:48:27 2021 -0600

    update changelog

commit cd28c73c8a
Author: Matthew Chambers <nr0q@gridtracker.org>
Date:   Mon Dec 13 19:04:23 2021 -0600

    update changelog

commit 058dbea415
Author: Matthew Chambers <nr0q@gridtracker.org>
Date:   Mon Dec 13 19:03:46 2021 -0600

    Fix #76

commit f50ea44466
Author: Matthew Chambers <nr0q@gridtracker.org>
Date:   Mon Dec 13 16:18:51 2021 -0600

    update changelog to recent bug fixes

commit 3b0c9b5acc
Author: Matthew Chambers <nr0q@gridtracker.org>
Date:   Mon Dec 13 16:18:37 2021 -0600

    Fix #91

commit d906ee7d5f
Author: Matthew Chambers <nr0q@gridtracker.org>
Date:   Mon Dec 13 15:54:51 2021 -0600

    Fixes #107

commit 8252ca3f82
Author: Matthew Chambers <nr0q@gridtracker.org>
Date:   Mon Dec 13 12:13:23 2021 -0600

    fix hunting

commit c1f3ae9e1c
Author: Sebastian Delmont <sd@notso.net>
Date:   Mon Dec 13 13:09:46 2021 -0500

    Really fix roster counts

commit 0054993dc8
Author: Sebastian Delmont <sd@notso.net>
Date:   Mon Dec 13 11:54:19 2021 -0500

    Fix roster counts

commit 69e1152e78
Author: Matthew Chambers <nr0q@gridtracker.org>
Date:   Mon Dec 13 10:09:19 2021 -0600

    update check for bad dxcc

commit a0b2595e9e
Author: Sebastian Delmont <sd@notso.net>
Date:   Mon Dec 13 11:04:53 2021 -0500

    Fixed spot sorting in refactored code

commit 298e8cfbd7
Author: Matthew Chambers <nr0q@gridtracker.org>
Date:   Sun Dec 12 16:37:52 2021 -0600

    update changelog

commit eb793d5607
Author: Matthew Chambers <nr0q@gridtracker.org>
Date:   Thu Dec 16 14:47:21 2021 -0600

    Update Copyright for 2022

commit 0eb2fac9a0
Author: Matthew Chambers <nr0q@gridtracker.org>
Date:   Thu Dec 16 14:46:52 2021 -0600

    change vars to lets per Tag's suggestion

commit c78ea075b4
Author: Matthew Chambers <nr0q@gridtracker.org>
Date:   Sun Dec 12 15:46:17 2021 -0600

    RC build

commit 0c5cde472b
Author: Matthew Chambers <nr0q@gridtracker.org>
Date:   Tue Nov 16 04:11:44 2021 +0000

    Update .gitlab-ci.yml file

commit 492b791bc0
Author: Matthew Chambers <nr0q@gridtracker.org>
Date:   Tue Nov 16 04:10:31 2021 +0000

    Update .gitlab-ci.yml

commit e77b9922ed
Author: Matthew Chambers <nr0q@gridtracker.org>
Date:   Tue Nov 16 03:56:53 2021 +0000

    Update .gitlab-ci.yml - include security scanning

commit 13c1236f7b
Author: Matthew Chambers <nr0q@gridtracker.org>
Date:   Thu Dec 16 14:46:20 2021 -0600

    Fix acknowledgement icons

commit 28772768e8
Author: Matthew Chambers <nr0q@gridtracker.org>
Date:   Thu Dec 16 14:45:31 2021 -0600

    Add support for Apple Silicon Macs, by hardcoding x64 mode in Phoenix

commit 0cec076dbb
Author: Matthew Chambers <nr0q@gridtracker.org>
Date:   Thu Dec 16 14:45:05 2021 -0600

    allow package-lock to be uploaded to repo

commit 8b23a4ef25
Author: Matthew Chambers <nr0q@gridtracker.org>
Date:   Sun Dec 12 09:11:24 2021 -0600

    beta III of call roster testing

commit cc476c84ed
Author: Matthew Chambers <nr0q@gridtracker.org>
Date:   Sun Dec 12 09:09:57 2021 -0600

    if dxcc = -1, no roster

commit ca5a4db664
Author: nr0q <nr0q@gridtracker.org>
Date:   Thu Dec 9 20:59:15 2021 -0600

    beta version for testing fix to CR

commit 5556bbfee0
Author: nr0q <nr0q@gridtracker.org>
Date:   Thu Dec 9 14:31:02 2021 -0600

    a few of SD's roster tweaks

commit 2b65f293a7
Author: nr0q <nr0q@gridtracker.org>
Date:   Thu Dec 9 13:53:20 2021 -0600

    could this cure the free text messages breaking the CR?

commit 43ea47a09d
Author: nr0q <nr0q@gridtracker.org>
Date:   Mon Oct 25 20:43:48 2021 -0500

    roll v for beta build

commit f1d9db2e6f
Author: nr0q <nr0q@gridtracker.org>
Date:   Mon Oct 25 15:17:33 2021 -0500

    better handling of /MM so that it doesn't tear a hole in space-time

commit 9fed1b4aca
Author: nr0q <nr0q@gridtracker.org>
Date:   Mon Oct 25 14:00:29 2021 -0500

    remove the exception handler for callObj.style because need to fix the root cause

commit 7a73c988da
Author: nr0q <nr0q@gridtracker.org>
Date:   Mon Oct 25 13:31:15 2021 -0500

    handle undefined callObj.style

commit 71a2df7e20
Author: nr0q <nr0q@gridtracker.org>
Date:   Mon Oct 25 12:42:58 2021 -0500

    handle bug line 114

commit 8d5117b76b
Author: nr0q <nr0q@gridtracker.org>
Date:   Sun Oct 24 20:36:10 2021 -0500

    inc v for beta 2

commit b199c4c4fa
Author: christian <christian_bay@gmx.de>
Date:   Sun Oct 24 21:23:40 2021 -0400

    fixed linting

commit 7830e52978
Author: nr0q <nr0q@gridtracker.org>
Date:   Sun Oct 24 20:15:07 2021 -0500

    cleaned up linting

commit ac51710ff3
Author: Christian Bayer <christian_bay@gmx.de>
Date:   Sun Oct 24 20:56:21 2021 -0400

    fixed reference error on huntedCount

commit 66f7ad87b3
Author: Matthew Chambers <nr0q@gridtracker.org>
Date:   Thu Dec 16 14:44:39 2021 -0600

    fix pack.json and changelog to reflect test V#

commit 7a43853533
Author: Matthew Chambers <nr0q@gridtracker.org>
Date:   Thu Dec 16 14:44:14 2021 -0600

    add settings.json to gitignore

commit 4f2ce9d890
Author: Matthew Chambers <nr0q@gridtracker.org>
Date:   Thu Oct 21 00:41:12 2021 +0000

    Update package.json

commit dbc297a00c
Author: Matthew Chambers <nr0q@gridtracker.org>
Date:   Thu Dec 16 14:43:52 2021 -0600

    Update package.json

commit 6c68a190db
Author: Matthew Chambers <nr0q@gridtracker.org>
Date:   Thu Dec 16 14:43:31 2021 -0600

    Update changelog

commit 3125b01a17
Author: christian <christian@t530>
Date:   Wed Jul 7 15:08:03 2021 -0400

    clear call roster on band change: option added

commit 6f4c15c157
Author: christian <christian@t530>
Date:   Sun Jul 4 23:07:51 2021 -0400

    unknown dxxc filter for roster

commit a444d163ca
Author: christian <christian@t530>
Date:   Thu Jul 1 21:39:50 2021 -0400

    fixed other sorts

commit cb73f21a93
Author: christian <christian@t530>
Date:   Wed Jun 30 20:37:27 2021 -0400

    fixed alert script call

commit 2226f707bd
Author: christian <christian@t530>
Date:   Wed Jun 30 07:52:36 2021 -0400

    fixed dxcc sorting

commit d395b8dd0e
Author: Matthew Chambers <nr0q@gridtracker.org>
Date:   Mon Jun 28 23:18:43 2021 -0500

    tweak for compact mode

commit 86fb507d5a
Author: Matthew Chambers <nr0q@gridtracker.org>
Date:   Mon Jun 28 23:08:13 2021 -0500

    IT WORKS!

commit d55ac551d1
Author: Matthew Chambers <nr0q@gridtracker.org>
Date:   Mon Jun 28 22:51:52 2021 -0500

    fix grid

commit 0a85e76493
Author: Matthew Chambers <nr0q@gridtracker.org>
Date:   Mon Jun 28 22:50:49 2021 -0500

    bunch of stuff moved to the right places

commit 68f81c6200
Author: Matthew Chambers <nr0q@gridtracker.org>
Date:   Mon Jun 28 22:37:49 2021 -0500

    fix some small stuff

commit db738a4230
Author: Matthew Chambers <nr0q@gridtracker.org>
Date:   Mon Jun 28 22:26:40 2021 -0500

    lost show bands/modes on render call rows

commit 68f7544b1a
Author: Matthew Chambers <nr0q@gridtracker.org>
Date:   Mon Jun 28 22:24:32 2021 -0500

    fix line 73

commit 95920077bd
Author: Matthew Chambers <nr0q@gridtracker.org>
Date:   Mon Jun 28 22:21:19 2021 -0500

    fix line 34

commit 84059439c1
Author: Matthew Chambers <nr0q@gridtracker.org>
Date:   Mon Jun 28 22:18:32 2021 -0500

    fix broken array

commit 817e9c5e18
Author: Matthew Chambers <nr0q@gridtracker.org>
Date:   Mon Jun 28 22:12:23 2021 -0500

    fix sendAlerts undefined object

commit 7a0b16d262
Author: Matthew Chambers <nr0q@gridtracker.org>
Date:   Mon Jun 28 22:08:06 2021 -0500

    more broke fixed

commit 6a9896ce41
Author: Matthew Chambers <nr0q@gridtracker.org>
Date:   Mon Jun 28 22:00:27 2021 -0500

    re-added r_sortFunction that somehow wondered off

commit 856a49b720
Author: Matthew Chambers <nr0q@gridtracker.org>
Date:   Mon Jun 28 21:58:05 2021 -0500

    fix some more broken stuff

commit 076a7e5eec
Author: Matthew Chambers <nr0q@gridtracker.org>
Date:   Mon Jun 28 20:42:07 2021 -0500

    fixed a bunch of broken refs to rosterSettings

commit 443409b902
Author: Matthew Chambers <nr0q@gridtracker.org>
Date:   Mon Jun 28 19:19:26 2021 -0500

    refactor so far

commit 1f45299286
Author: Matthew Chambers <nr0q@gridtracker.org>
Date:   Mon Jun 28 17:26:44 2021 -0500

    big roster refactor - starting

    Co-authored-by: Sebastian Delmont <sd@notso.net>
    Matthew Chambers <nr0q@gridtracker.org>

commit 4ed8b2c3cb
Author: Matthew Chambers <nr0q@gridtracker.org>
Date:   Thu Jun 24 18:46:42 2021 -0500

    missing comma line 422

commit b089caf50a
Author: Matthew Chambers <nr0q@gridtracker.org>
Date:   Thu Jun 24 18:04:46 2021 -0500

    add array with exception test function names, need to create functions yet

commit 0b27feb367
Author: Matthew Chambers <nr0q@gridtracker.org>
Date:   Thu Jun 24 11:06:31 2021 -0500

    some notes that might aid in refactoring

commit 0518d6e40c
Author: Matthew Chambers <nr0q@gridtracker.org>
Date:   Thu Dec 16 14:42:44 2021 -0600

    add functions to get acks json off website and overwrite file

commit 268459833b
Author: Matthew Chambers <nr0q@gridtracker.org>
Date:   Thu Dec 16 14:41:03 2021 -0600

    Initial workup for LoTW throttling & diff fetching

commit 9330df84f3
Author: nr0q <nr0q@gridtracker.org>
Date:   Sun Oct 24 12:59:29 2021 -0500

    save work so far

commit 0761163ddd
Author: nr0q <nr0q@gridtracker.org>
Date:   Tue Oct 19 21:54:26 2021 -0500

    adding i18n to other html files, need to call scripts I think to make them "work"

commit 3a00b5b3d0
Author: nr0q <nr0q@gridtracker.org>
Date:   Tue Oct 19 21:16:02 2021 -0500

    i18n chat html and format chat.css

commit 220fc036b8
Author: nr0q <nr0q@gridtracker.org>
Date:   Tue Oct 19 20:57:05 2021 -0500

    refactor chat css into it's own css file, fix linting in gt.js start adding i18n in chat and bandactivity htmls

commit fceaaaa4aa
Author: nr0q <nr0q@gridtracker.org>
Date:   Tue Oct 19 19:39:21 2021 -0500

    update all except hover/title elements with i18n in GridTracker.html

commit 215bc2c55c
Author: nr0q <nr0q@gridtracker.org>
Date:   Tue Oct 19 18:28:48 2021 -0500

    mostly finished with gridtracker.html file's i18n

commit 9a63953b7d
Author: nr0q <nr0q@gridtracker.org>
Date:   Tue Oct 19 17:58:13 2021 -0500

    all through Audio Alerts done

commit bbe38ea60d
Author: nr0q <nr0q@gridtracker.org>
Date:   Tue Oct 19 17:05:47 2021 -0500

    check in everything up to mid alert settings

commit 99d89f68fc
Author: nr0q <nr0q@gridtracker.org>
Date:   Tue Oct 19 13:00:00 2021 -0500

    fix badly broken HTML

commit 934f097b70
Author: nr0q <nr0q@gridtracker.org>
Date:   Tue Oct 19 12:39:04 2021 -0500

    update through to Lookup tab

commit efd03b85ae
Author: chrbayer84 <christian_bay@gmx.de>
Date:   Wed Sep 29 18:04:22 2021 +0000

    Update README.md

commit ac5299cbb5
Author: nr0q <nr0q@gridtracker.org>
Date:   Wed Sep 29 12:26:50 2021 -0500

    add Getting GridTracker to readme

commit 8f3a7f81ae
Author: nr0q <nr0q@gridtracker.org>
Date:   Tue Sep 28 14:58:22 2021 -0500

    copy of NWJS's license

commit 645b2222b0
Author: T Loomis <tag.loomis@gmail.com>
Date:   Tue Sep 28 19:09:45 2021 +0000

    Removed OAMS messaging pop-up reset

commit 17035c84a0
Author: Matthew Chambers <nr0q@gridtracker.org>
Date:   Mon Sep 27 18:04:00 2021 +0000

    updated arm to NWJS 0.54.2 with 64 bit capability
    rolled to v1.21.0928

commit 75421054f9
Author: Matthew Chambers <nr0q@gridtracker.org>
Date:   Mon Sep 27 18:00:48 2021 +0000

    Treat adif record values as byte length vs string length

commit 44d54dd5df
Author: Matthew Chambers <NR0Q@gridtracker.org>
Date:   Thu Sep 16 20:37:04 2021 -0500

    updated V-num for beta build

commit 50c65ac2c4
Author: jangliss <jon+gh@netdork.net>
Date:   Thu Sep 16 20:27:21 2021 -0500

    Remove looking at fetched records for last fetch date for LoTW. Use only header

commit 421601e36d
Author: Matthew Chambers <NR0Q@gridtracker.org>
Date:   Sun Aug 29 14:39:18 2021 -0500

    new donors yay

commit 3eb3fa4b21
Author: Matthew Chambers <NR0Q@gridtracker.org>
Date:   Sat Aug 28 13:06:48 2021 -0500

    acks data update

commit cdb524a887
Author: Matthew Chambers <NR0Q@gridtracker.org>
Date:   Wed Aug 25 14:38:51 2021 -0500

    data update

commit f91cc0968c
Author: Matthew Chambers <nr0q@gridtracker.org>
Date:   Mon Jul 5 11:47:16 2021 -0500

    acks update 5-july-2021

commit 0ca37bf71e
Author: Matthew Chambers <nr0q@gridtracker.org>
Date:   Tue Jun 29 16:41:47 2021 -0500

    ack update 29 July 2021

commit 53f6168e23
Author: Matthew Chambers <nr0q@gridtracker.org>
Date:   Tue Jun 22 11:49:53 2021 -0500

    update acknowledgements.json for 6/22/2021

commit 2b79d75f09
Author: Matthew Chambers <nr0q@gridtracker.org>
Date:   Sun Jun 20 13:13:40 2021 -0500

    update acknowledgements.json

commit c30d004c69
Author: Matthew Chambers <nr0q@gridtracker.org>
Date:   Sat Jun 19 16:19:52 2021 -0500

    update acknowledgements.json

commit c3bef85eab
Author: Matthew Chambers <nr0q@gridtracker.org>
Date:   Sat Jun 19 20:58:02 2021 +0000

    Update acks json

commit 260e4bc9bc
Author: Matthew Chambers <nr0q@gridtracker.org>
Date:   Sat Jun 19 12:01:43 2021 -0500

    general updates for new general release

commit fc742c95a8
Author: Matthew Chambers <nr0q@gridtracker.org>
Date:   Sat Jun 19 14:36:13 2021 -0500

    fix line 15581

commit 6a04b9cb7b
Author: Matthew Chambers <nr0q@gridtracker.org>
Date:   Sat Jun 19 13:44:44 2021 -0500

    more better

commit 229efb099a
Author: Matthew Chambers <nr0q@gridtracker.org>
Date:   Sat Jun 19 13:26:06 2021 -0500

    better get acks code (Thanks Tag)

commit 7b30fb3093
Author: Matthew Chambers <nr0q@gridtracker.org>
Date:   Sat Jun 19 11:43:05 2021 -0500

    fix missing " around http line 11141

commit 24e180ffdc
Author: Matthew Chambers <nr0q@gridtracker.org>
Date:   Sat Jun 19 11:33:04 2021 -0500

    call checkForNewAcks when checkForNewVersion

commit e9d9f8b24a
Author: Matthew Chambers <nr0q@gridtracker.org>
Date:   Sat Jun 19 11:17:29 2021 -0500

    add functions to get acks json off website and overwrite file

commit 56e4d58169
Author: jangliss <jon+gh@netdork.net>
Date:   Fri Jun 18 20:28:25 2021 -0500

    Date.parse behavior to local time instead of UTC

commit 74db81d764
Author: jangliss <jon+gh@netdork.net>
Date:   Thu Jun 17 17:56:37 2021 -0500

    More LoTW Fixes to do diff fetching

commit cedeef59f8
Author: jangliss <jon+gh@netdork.net>
Date:   Tue Jun 15 21:03:15 2021 -0500

    Initial workup for LoTW throttling & diff fetching

commit 4576c519c8
Author: Santiago Mejia <santiago.hi8smx@gmail.com>
Date:   Wed Jun 16 19:59:05 2021 +0000

    Upload New File

commit f79010707a
Author: jangliss <jon+gh@netdork.net>
Date:   Sat Jun 19 15:44:51 2021 -0500

    Fix linting warning

commit 9b31e8c1a8
Author: Matthew Chambers <nr0q@gridtracker.org>
Date:   Sat Jun 12 22:13:03 2021 -0500

    update changelog etc for v1.21.0613

commit 3706978e8b
Author: Matthew Chambers <nr0q@gridtracker.org>
Date:   Sun Jun 13 03:27:38 2021 +0000

    Update acks json

commit bbd17c1e32
Author: jangliss <jon+gh@netdork.net>
Date:   Sat Jun 12 22:20:32 2021 -0500

    Linting hates me. Remove space on comment.

commit 80466b0eda
Author: jangliss <jon+gh@netdork.net>
Date:   Sat Jun 12 22:08:47 2021 -0500

    Fix npm wanting a space after comment syntax

commit 5791ba583e
Author: jangliss <jon+gh@netdork.net>
Date:   Sat Jun 12 21:55:50 2021 -0500

    Temporarily disable LoTW full downloads on startup

commit d5478ee4ab
Author: nr0q <nr0q@gridtracker.org>
Date:   Mon Oct 18 17:17:41 2021 -0500

    small fixes in typos in data-i18n tags

commit ec541a5a83
Author: nr0q <nr0q@gridtracker.org>
Date:   Mon Oct 18 14:08:50 2021 -0500

    it all works and created es file for Santiago to start on

commit 6c14637639
Author: nr0q <nr0q@gridtracker.org>
Date:   Mon Oct 18 13:51:09 2021 -0500

    loading the local file helps, added a statup function to do that

commit 6354317358
Author: nr0q <nr0q@gridtracker.org>
Date:   Wed Oct 13 16:25:07 2021 -0500

    add .vscode to gitignore

commit 27cc542b65
Author: nr0q <nr0q@gridtracker.org>
Date:   Wed Oct 13 10:20:55 2021 -0500

    finished i18n tags through map vew filters

commit ef4683c8ea
Author: nr0q <nr0q@gridtracker.org>
Date:   Tue Oct 12 20:23:12 2021 -0500

    added data-i18n tags up through mapFilter.mode

commit 0aa862afbe
Author: nr0q <nr0q@gridtracker.org>
Date:   Tue Oct 12 16:49:03 2021 -0500

    more data-i18n tags

commit bbd39a640f
Author: nr0q <nr0q@gridtracker.org>
Date:   Tue Oct 12 16:07:39 2021 -0500

    adding data-i18n fields to tags

commit 603c8c039d
Author: nr0q <nr0q@gridtracker.org>
Date:   Mon Oct 11 17:37:11 2021 -0500

    all HTML files done

commit 7e97e9d2af
Author: nr0q <nr0q@gridtracker.org>
Date:   Mon Oct 11 16:08:52 2021 -0500

    i18n up to the about tab

commit 0c65ab8f3a
Author: nr0q <nr0q@gridtracker.org>
Date:   Mon Oct 11 13:51:09 2021 -0500

    i18n en strings through audio settings

commit 39152109a5
Author: nr0q <nr0q@gridtracker.org>
Date:   Mon Oct 11 13:18:35 2021 -0500

    cleaner keys

commit 59a93e3f30
Author: nr0q <nr0q@gridtracker.org>
Date:   Mon Oct 11 11:46:28 2021 -0500

    i18n through control panel

commit 17be5a2843
Author: nr0q <nr0q@gridtracker.org>
Date:   Mon Oct 11 10:43:25 2021 -0500

    check in what I have so far

commit aa65ad9936
Author: christian <christian@t530>
Date:   Sun Jun 13 14:21:43 2021 -0400

    added jquery.i18n

commit 9d31645823
Author: christian <christian@t530>
Date:   Wed Jun 9 21:29:23 2021 -0400

    i18n hook for main gt.html

commit 7e9e5b9cfe
Author: christian <christian@t530>
Date:   Mon May 24 21:08:15 2021 -0400

    WIP banana i18n
merge-requests/192/head
Christian Bayer 2022-09-05 21:57:15 -04:00 zatwierdzone przez Tag
rodzic 6b32701b66
commit d28b48cc1e
33 zmienionych plików z 17196 dodań i 3898 usunięć

2
.gitignore vendored
Wyświetl plik

@ -11,4 +11,4 @@ debian/tmp
node_modules
package-lock.json
.vscode
desktop.ini
desktop.ini

4032
package-lock.json wygenerowano

Plik diff jest za duży Load Diff

Wyświetl plik

@ -18,6 +18,7 @@
"dist-win": "build --concurrent --tasks win-x86,win-x64 package.nw",
"distsome": "build --debug --tasks linux-x64,mac-x64 package.nw",
"start": "run package.nw",
"start-x64": "run --x64 package.nw"
"start-x64": "run --x64 package.nw",
"postinstall": "cd package.nw && npm install"
}
}

Wyświetl plik

@ -16,7 +16,7 @@
<html lang="en" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Band Activity</title>
<title data-i18n="bandactivity.title">Band Activity</title>
<link rel="stylesheet" href="./lib/style.css" />
<script src="./lib/protos.js" type="text/javascript"></script>
<script src="./lib/screens.js" type="text/javascript"></script>
@ -69,7 +69,7 @@
"
title="PSK-Reporter Band Activity"
>
<div id="graphDiv" style="bottom: 0; position: absolute; width: 100%; padding: 0px; margin-bottom: 2px">
<div data-i18n="bandactivity.noData" id="graphDiv" style="bottom: 0; position: absolute; width: 100%; padding: 0px; margin-bottom: 2px">
<br />...no data yet...<br />
&nbsp;
</div>

Wyświetl plik

@ -15,117 +15,10 @@
-->
<html xmlns="http://www.w3.org/1999/xhtml" style="height: 100%; width: 100%">
<head>
<title>Off-Air Message Service (OAMS)</title>
<title data-i18n="chat.title">Off-Air Message Service (OAMS)</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<link rel="stylesheet" href="./lib/style.css" />
<style type="text/css">
table,
th,
td,
body,
input {
color: #fff;
white-space: nowrap;
font-family: Sans-Serif;
font-size: 13px;
text-align: auto;
}
.boxDisplay {
margin: 1px;
padding: 2px;
border-width: 2px;
border-color: #aaa;
border-style: inset;
vertical-align: top;
-webkit-border-radius: 4px;
}
textarea {
width: 100%;
resize: none;
font-size: 15px;
}
.self {
color: #ffff00;
font-weight: bold;
}
.them {
color: #00ffff;
font-weight: bold;
}
.system {
color: #ff0000;
font-weight: bold;
}
.when {
color: #777777;
font-size: 12px;
}
.msgText {
color: #eeeeee;
font-size: 15px;
}
.msgTextUnicode {
color: #eeeeee;
font-size: 15px;
}
body {
background-image: url(img/gridtracker10.png);
background-repeat: no-repeat;
background-attachment: fixed;
background-position: center;
}
#callsign {
color: #00ffff;
font-weight: bold;
}
#country,
#dxcc {
color: #ffff00;
font-weight: bold;
}
#grid {
color: orange;
font-weight: bold;
}
#band {
color: #009900;
font-weight: bold;
}
#mode {
color: #ee0000;
font-weight: bold;
}
.rosterOn {
color: #ffffff;
}
.rosterOff {
color: #777777;
}
.imgGray {
-webkit-filter: grayscale(1); /* Google Chrome, Safari 6+ & Opera 15+ */
}
.imgNoFilter {
}
input:focus,
textarea:focus,
select:focus {
outline: none;
}
table {
border-collapse: collapse;
}
tr:hover td {
box-shadow: inset 0px 11px 6px -8px #888, inset 0px -11px 6px -8px #888;
}
</style>
<link rel="stylesheet" href="./lib/chat.css" />
<script src="./lib/protos.js" type="text/javascript"></script>
<script src="./lib/third-party.js" type="text/javascript"></script>
<script src="./lib/screens.js"></script>
@ -563,31 +456,25 @@
</head>
<body onLoad="init();" style="height: 100%; width: 100%" onresize="Resize();">
<div id="noticeDiv" style="display: none; width: 80%; overflow-wrap: break-word; white-space: normal">
<p data-i18n="chat.notice.para1">
<b>NOTICE</b>: GridTracker chat is not encrypted or obfuscated beyond HTTPS. This means that it's sent as
plaintext that is vulnerable to hackers, pirates, the NSA, your wife, and anyone that thinks you're interesting
enough to monitor.
<p>
</p>
<p data-i18n="chat.notice.para2">
<b>NEVER</b> give passwords, credit card numbers, safe combinations or any personal information that you don't
want bad people to know because there are some very bad people out there.
</p>
<p>
<p data-i18n="chat.notice.para3">
Not us, though. While GridTracker is free, unlike some other free apps, we don't store, save, sell, peek at or
otherwise do anything with the chat that would violate your trust. We don't keep logs. We don't save Metadata.
We just don't.
</p>
<p>
<p data-i18n="chat.notice.para4">
Close GridTracker, lose the text. So write anything down you want to save.
<br />Because when it's gone, gone is forever.
</p>
<p>
<br />
</p>
<p></p>
<div class="button" onclick="userAgrees();">Click here to acknowledge the above and enable messaging</div>
<div data-i18n="chat.notice.agree" class="button" onclick="userAgrees();">Click here to acknowledge the above and enable messaging</div>
</div>
<div id="wrapperDiv" style="display: none">
<div
@ -624,11 +511,11 @@
"
>
<div style="display: inline-block; cursor: pointer" onclick="toggleBand()">
<font color="lightgreen">Band: </font>
<font data-i18n="chat.filter.band" color="lightgreen">Band: </font>
<font id="viewBand" color="yellow">All</font>
</div>
<div style="display: inline-block; cursor: pointer" onclick="toggleMode()">
<font color="orange">Mode: </font>
<font data-i18n="chat.filter.mode" color="orange">Mode: </font>
<font id="viewMode" color="yellow">All</font>
</div>
</div>

Wyświetl plik

@ -15,7 +15,7 @@
-->
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Current Conditions</title>
<title data-i18n="conditions.title">Current Conditions</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<link rel="stylesheet" href="./lib/style.css" />
<style type="text/css">

Wyświetl plik

@ -17,7 +17,7 @@
<html lang="en" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Callsign Lookup</title>
<title data-i18n="lookup.title">Callsign Lookup</title>
<link rel="stylesheet" href="./lib/style.css" />
<script src="./lib/protos.js" type="text/javascript"></script>
<script src="./lib/screens.js"></script>
@ -118,25 +118,20 @@
>
<div id="lookupBoxDiv" class="lookupContent" style="display: block; overflow: auto; overflow-x: hidden">
<div>
Callsign<input
id="lookupCallsignInput"
type="text"
class="inputTextValue"
size="12"
onkeyup="if (event.keyCode === 13) lookupButtonID.click();"
oninput="ValidateCallsign(this,null);"
/>
<label data-i18n="lookup.callsign.label" for="lookupCallsignInput">Callsign</label>
<input
id="lookupCallsignInput" type="text" class="inputTextValue" size="12" onkeyup="if (event.keyCode === 13) lookupButtonID.click();" oninput="ValidateCallsign(this,null);"/>
<div
data-i18n="lookup.callsign.button"
id="lookupButtonID"
title="Lookup Callsign"
class="button"
onclick="if ( ValidateCallsign(lookupCallsignInput,null) ) { lookupCallsign(lookupCallsignInput.value, null, false);}"
>
onclick="if ( ValidateCallsign(lookupCallsignInput,null) ) { lookupCallsign(lookupCallsignInput.value, null, false);}">
Lookup
</div>
</div>
<div id="lookupLocalDiv"></div>
<div id="lookupInfoDiv">No Callsign information to display<br />try a lookup!</div>
<div data-i18n="lookup.noinfo" id="lookupInfoDiv">No Callsign information to display<br />try a lookup!</div>
</div>
</div>
</body>

Wyświetl plik

@ -15,7 +15,7 @@
-->
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Data Breakout</title>
<title data-i18n="popup.title">Data Breakout</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<link rel="stylesheet" href="./lib/style.css" />
<style type="text/css">

Wyświetl plik

@ -15,13 +15,22 @@
-->
<html xmlns="http://www.w3.org/1999/xhtml" style="height: 100%; width: 100%">
<head>
<title>Call Roster</title>
<title data-i18n="roster.title">Call Roster</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<link rel="stylesheet" href="./lib/style.css" />
<link id="roster" rel="stylesheet" href="./lib/style_roster.css" />
<script src="./lib/protos.js" type="text/javascript"></script>
<script src="./lib/third-party.js" type="text/javascript"></script>
<script src="./lib/roster.js" type="text/javascript"></script>
<script src="node_modules/jquery/dist/jquery.js" type="text/javascript"></script>
<script src="./lib/CLDRPluralRuleParser.js" type="text/javascript"></script>
<script src="./lib/jquery.i18n.js" type="text/javascript"></script>
<script src="./lib/jquery.i18n.messagestore.js" type="text/javascript"></script>
<script src="./lib/jquery.i18n.fallbacks.js" type="text/javascript"></script>
<script src="./lib/jquery.i18n.parser.js" type="text/javascript"></script>
<script src="./lib/jquery.i18n.emitter.js" type="text/javascript"></script>
<script src="./lib/jquery.i18n.language.js" type="text/javascript"></script>
<script src="./lib/i18n.js" type="text/javascript"></script>
<script src="./lib/roster.js " type="text/javascript"></script>
<script src="./lib/roster/prepareRosterSettings.js" type="text/javascript"></script>
<script src="./lib/roster/processRosterFiltering.js" type="text/javascript"></script>
<script src="./lib/roster/processRosterHunting.js" type="text/javascript"></script>
@ -31,84 +40,73 @@
<script src="./lib/roster/rosterColumns.js" type="text/javascript"></script>
<script src="./lib/roster/rosterColumnFunctions.js" type="text/javascript"></script>
<script src="./lib/roster/sendAlerts.js" type="text/javascript"></script>
<script src="./lib/screens.js"></script>
<script src="./lib/screens.js" type="text/javascript"></script>
</head>
<body onload="init()" class="roster" oncontextmenu="return handleContextMenu(event);">
<div id="MainCallRoster">
<header id="RosterControls">
<div id="TransmitControls">
<div
id="txrxdec"
style="
background-color: Green;
border-style: outset;
border-color: yellow;
border-width: 3px;
margin: 2px;
"
class="roundBorder"
>
Waiting…
<div id="txrxdec" style=" background-color: Green; border-style: outset; border-color: yellow; border-width: 3px; margin: 2px;" class="roundBorder">
Waiting…
</div>
<div class="button" style="margin: 3px" onclick="window.opener.haltAllTx(true);">Halt Tx</div>
</div>
<div id="MoreLessControls">
<div class="link" onclick="toggleMoreControls()" id="ShowMoreControlsLink">More Controls</div>
<div class="link" onclick="toggleMoreControls()" id="ShowFewerControlsLink">Fewer Controls</div>
<div data-i18n="roster.controls.more" class="link" onclick="toggleMoreControls()" id="ShowMoreControlsLink">More Controls</div>
<div data-i18n="roster.controls.less" class="link" onclick="toggleMoreControls()" id="ShowFewerControlsLink">Fewer Controls</div>
</div>
<div id="MainRosterControls">
<div id="LogbookControls">
<label>Logbook</label>
<label data-i18n="roster.controls.logbook.label">Logbook</label>
<select id="referenceNeed" onchange="valuesChanged();">
<option value="6">Award Tracker</option>
<option value="0">Live Band &amp; Mode</option>
<option value="1">Live Band, Mix Modes</option>
<option value="2">Live Band, Digi Modes</option>
<option value="3">Mix Band, Live Mode</option>
<option value="4">Mix Band &amp; Modes</option>
<option value="5">Mix Band &amp; Digi Modes</option>
<option data-i18n="roster.controls.logbook.awardTracker" value="6">Award Tracker</option>
<option data-i18n="roster.controls.logbook.liveBandMode" value="0">Live Band &amp; Mode</option>
<option data-i18n="roster.controls.logbook.liveBandMixMode" value="1">Live Band, Mix Modes</option>
<option data-i18n="roster.controls.logbook.liveBandDigiMode" value="2">Live Band, Digi Modes</option>
<option data-i18n="roster.controls.logbook.mixBandLiveMode" value="3">Mix Band, Live Mode</option>
<option data-i18n="roster.controls.logbook.mixBandMode" value="4">Mix Band &amp; Modes</option>
<option data-i18n="roster.controls.logbook.mixBandDigiMode" value="5">Mix Band &amp; Digi Modes</option>
</select>
</div>
<div id="CallsignsControls">
<label>Callsigns</label>
<label data-i18n="roster.controls.callsigns.label">Callsigns</label>
<select id="callsignNeed" onchange="valuesChanged();">
<option value="worked">New</option>
<option value="confirmed">New+Unconfirmed</option>
<option value="all">All Traffic</option>
<option value="hits">All Traffic/Only Wanted</option>
<option data-i18n="roster.controls.callsigns.worked" value="worked">New</option>
<option data-i18n="roster.controls.callsigns.confirmed" value="confirmed">New+Unconfirmed</option>
<option data-i18n="roster.controls.callsigns.all" value="all">All Traffic</option>
<option data-i18n="roster.controls.callsigns.hits" value="hits">All Traffic/Only Wanted</option>
</select>
</div>
<div id="HuntModeControls">
<label>Hunting</label>
<label data-i18n="roster.controls.hunting.label">Hunting</label>
<select id="huntMode" onchange="valuesChanged();" value="callsign">
<option value="callsign">Callsign</option>
<option value="grid">Grid</option>
<option value="dxcc">DXCC</option>
<option value="dxccs">DXCC (Single)</option>
<option value="cq">CQ Zone</option>
<option value="itu">ITU Zone</option>
<option value="usstates">US States (WAS)</option>
<option value="usstate">US State (Single)</option>
<option value="wpx">Prefix (WPX)</option>
<option data-i18n="roster.controls.hunting.callsign" value="callsign">Callsign</option>
<option data-i18n="roster.controls.hunting.grid" value="grid">Grid</option>
<option data-i18n="roster.controls.hunting.dxcc" value="dxcc">DXCC</option>
<option data-i18n="roster.controls.hunting.dxccSingle" value="dxccs">DXCC (Single)</option>
<option data-i18n="roster.controls.hunting.cqZone" value="cq">CQ Zone</option>
<option data-i18n="roster.controls.hunting.ituZone" value="itu">ITU Zone</option>
<option data-i18n="roster.controls.hunting.usStates" value="usstates">US States (WAS)</option>
<option data-i18n="roster.controls.hunting.usState" value="usstate">US State (Single)</option>
<option data-i18n="roster.controls.hunting.wpx"value="wpx">Prefix (WPX)</option>
</select>
<select id="huntNeed" onchange="valuesChanged();">
<option value="worked">New</option>
<option value="confirmed">New+Unconfirmed</option>
<option value="mixed">Mixed</option>
<option data-i18n="roster.controls.huntNeed.worked" value="worked">New</option>
<option data-i18n="roster.controls.huntNeed.confirmed" value="confirmed">New+Unconfirmed</option>
<option data-i18n="roster.controls.huntNeed.mixed" value="mixed">Mixed</option>
</select>
<select id="stateSelect" onchange="valuesChanged();">
<option value="" selected="true">Select Territory</option>
<option data-i18n="roster.controls.huntState.label"value="" selected="true">Select Territory</option>
</select>
<select id="DXCCsSelect" onchange="valuesChanged();" id="HuntDXCCsControls">
<option value="-1" selected="true">Select DXCC</option>
<option data-i18n="roster.controls.huntDXCC.label" value="-1" selected="true">Select DXCC</option>
</select>
</div>
@ -117,30 +115,30 @@
<div id="AwardTrackerControls">
<div id="AwardWantedList"></div>
<div class="button" onclick="openAwardPopup()">Add Awards</div>
<div data-i18n="roster.controls.awardTracker.addButton" class="button" onclick="openAwardPopup()">Add Awards</div>
<div id="awardHunterDiv" style="display: none;">
<table style="padding: 15px">
<tr>
<th align="center">New Award Tracker</th>
<th data-i18n="roster.controls.awardTracker.new" align="center">New Award Tracker</th>
</tr>
<tr>
<td align="left">
<select id="awardSponsor" onchange="awardSponsorChanged();">
<option value="" disabled selected>Sponsor</option>
<option data-i18n="roster.controls.awardTracker.sponsor" value="" disabled selected>Sponsor</option>
</select>
</td>
</tr>
<tr>
<td align="left">
<select id="awardName" onchange="awardNameChanged();">
<option value="" disabled selected>Name</option>
<option data-i18n="roster.controls.awardTracker.name" value="" disabled selected>Name</option>
</select>
</td>
</tr>
<tr>
<td align="center">
<div class="button" style="margin: 3px" onclick="closeAwardPopup()">Done</div>
<div data-i18n="roster.controls.awardTracker.add" class="button" style="margin: 3px" onclick="closeAwardPopup()">Done</div>
</td>
</tr>
</table>
@ -151,37 +149,40 @@
<div id="SecondaryRosterControls">
<div id="huntingMatrixDiv" class="secondaryControlGroup">
<h3>Wanted</h3>
<h3 data-i18n="roster.secondary.wanted.label">Wanted</h3>
<div class='columns'>
<div>
<label><input type="checkbox" id="huntCallsign" onchange="wantedChanged(this);" /> Callsign</label>
<input type="checkbox" id="huntCallsign" onchange="wantedChanged(this);" />
<label data-i18n="roster.secondary.wanted.callsign" for="huntCallsign">Callsign</label>
</div>
<div>
<label><input type="checkbox" id="huntGrid" onchange="wantedChanged(this);" /> Grid</label>
<input type="checkbox" id="huntGrid" onchange="wantedChanged(this);" />
<label data-i18n="roster.secondary.wanted.grid" for="huntGrid">Grid</label>
</div>
<div>
<label ><input type="checkbox" id="huntDXCC" onchange="wantedChanged(this);" /> DXCC</label>
<input type="checkbox" id="huntDXCC" onchange="wantedChanged(this);" />
<label data-i18n="roster.secondary.wanted.dxcc" for="huntDXCC">DXCC</label>
</div>
<div>
<label title="Stations calling *you*">
<input type="checkbox" id="huntQRZ" onchange="wantedChanged(this);" /> QRZ
</label>
<input type="checkbox" id="huntQRZ" onchange="wantedChanged(this);" />
<label data-i18n="roster.secondary.wanted.qrz" for="huntQRZ" title="Stations calling *you*">QRZ</label>
</div>
<div>
<label><input type="checkbox" id="huntPX" onchange="wantedChanged(this);" /> WPX</label>
<input type="checkbox" id="huntPX" onchange="wantedChanged(this);" />
<label data-i18n="roster.secondary.wanted.wpx" for="huntPX">WPX</label>
</div>
<div id="huntingMatrixPotaDiv">
<label title="Parks On The Air">
<input type="checkbox" id="huntPOTA" onchange="wantedChanged(this);" /> POTA
</label>
<input type="checkbox" id="huntPOTA" onchange="wantedChanged(this);" />
<label data-i18n="roster.secondary.wanted.pota" for="huntPOTA" title="Parks On The Air">POTA</label>
</div>
<div>
<label title="Off-Air Message Service Users">
<input type="checkbox" id="huntOAMS" onchange="wantedChanged(this);" /> OAMS
</label>
<div>
<input type="checkbox" id="huntOAMS" onchange="wantedChanged(this);" />
<label data-i18n="roster.secondary.wanted.OAMS" for="huntOAMS" title="Off-Air Message Service Users">OAMS</label>
</div>
<div>
</div>
<div>
<label><input type="checkbox" id="huntCQz" onchange="wantedChanged(this);" /> CQz</label>
</div>

Wyświetl plik

@ -0,0 +1,671 @@
{
"@metadata": {
"authors": [
"The GridTracker Team"
],
"last-updated": "2021-10-11",
"locale": "cn",
"message-documentation": "qqq"
},
"appname-sub-title": "2Grid网格跟踪助手",
"startupStatusDiv": "初始化启动",
"documents.Div1": "您的文件夹",
"legend.title": "图",
"legend.QSO.label": "您曾经通过的电台网格",
"legend.QSL.label": "您曾经通过并确认的电台网格",
"legend.QSX.label": "其他正在通联带网格的电台",
"legend.CQ.label": "网格内的电台正在呼叫CQ",
"legend.CQDX.label": "网格内的电台正在呼叫CQ远距离电台",
"legend.QRZ.label": "网格内的电台正在呼叫您",
"legend.QTH.label": "您所在的网格",
"legend.WSPR.label": "电台",
"appname-title": "单击隐藏菜单",
"quickLoad.clearLive.label": "清除来自GridTracker的实时数据",
"quickLoad.clearLog.label": "清除或重新载入日志数据 (不会删除文件",
"mapFilter.title.label": "地图视图筛选",
"mapFilter.band.label": "选择波段 (自动跟踪 WSJT-X)",
"mapFilter.band.OOB": "自动模式",
"mapFilter.mode.label": "选择模式",
"mapFilter.mode.Phone": "自动模式",
"mapFilter.prop.label": "选择传播模式视图",
"mapFilter.prop.TropoDuct": "混合模式",
"mapFilter.data.label": "数据",
"mapFilter.data.LogLive": "循环显示",
"settings.general.AppStatus.label": "应用软件状态",
"settings.general.UDP.Messages.label": "接收UDP信息",
"settings.general.UDP.Multicast.label": "启用/禁用本地组播网络",
"settings.general.UDP.IP.label": "IP地址",
"settings.general.UDP.Port.label": "端口",
"settings.general.Fwd.Messages.label1": "转发UDP信息",
"settings.general.Fwd.Messages.label2": "例如, 在另一个主机上的GridTracker",
"settings.general.Fwd.IP.label": "IP",
"settings.general.Fwd.Port.label": "端口",
"settings.general.Fwd.Enabled.label": "启用?",
"settings.general.CenterGrid.label": "所在网格",
"settings.general.DistanceUnits.label": "距离单位",
"settings.general.Distance.dg": "KM公里",
"settings.general.DecodeWaterfall.label": "右下角解码信息框",
"settings.general.CheckNewVersion.label": "检查新版本",
"settings.general.ClearAllSettings.label": "清除所有设置",
"settings.general.ClearSettingSure.label": "是的, 我确定!",
"settings.general.ExportSettings.label": "导出设置",
"settings.general.ImportSettings.label": "导入设置",
"settings.lookup.label": "呼号查找服务",
"settings.lookup.QRZCQ": "C A L L O O K(仅限美国)",
"settings.lookup.Username.label": "用户姓名",
"settings.lookup.QRZTest": "测试",
"settings.lookup.AddData.label": "将寻找得到的资料增加至QSO纪录中",
"settings.lookup.AddGrid.label": "如果缺少QSO网格则增加查找网格数据",
"settings.lookup.OpenOnTx.label": "在传输时打开查找",
"settings.lookup.CloseOnLog.label": "记录日志后关闭查找",
"settings.lookup.CallookFirst.label": "使用其他服务之前使用呼号查找",
"settings.lookup.Databases.label": "呼号数据库",
"settings.lookup.Count.header": "数据库",
"settings.audio.TextToSpeech.label": "文本朗读语言包",
"settings.audio.Speech.Rate.label": "朗读速度",
"settings.audio.Speech.Pitch.label": "朗读音调",
"settings.audio.Speech.Volume.label": "朗读音量",
"settings.audio.Speech.Phonetics.label": "朗读说出呼号和网格的音质",
"settings.audio.Device.label": "音频设备",
"settings.audio.File.Volume.label": "音频文件音量",
"settings.audio.lighteningAlert.label": "雷电音频警报",
"settings.audio.lighteningAlert.voice": "0无声",
"settings.audio.QSOLogEventFile.label": "日志事件通知",
"settings.logbook.callsigns.label": "曾经通联的呼号",
"settings.logbook.callsigns.enable": "启用筛选",
"settings.logbook.callsigns.callsigns": "呼号(s)",
"settings.logbook.date.label": "通联日",
"settings.logbook.date.enable": "启用?",
"settings.apply.label": "",
"settings.grids.reset.title": "网格颜色",
"settings.grids.reset.label": "将网格颜色重置为预设值",
"settings.grids.QSO.label": "曾经",
"settings.grids.QSL.label": "已经确",
"settings.grids.QSX.label": "其他正在通联的电",
"settings.grids.CQ.label": "的电",
"settings.grids.CQDX.label": "的电",
"settings.grids.QRZ.label": "您的通联",
"settings.grids.QTH.label": "您的网格",
"settings.grids.spotsOverGrids.label": "将接收Spots放置在网格图层上",
"settings.grids.opacity.label": "网格透明度",
"settings.grids.splitQSL.label": "分离QSL网格",
"settings.grids.AutoMouseOver.label": "鼠标自动移至网格",
"settings.grids.liveDecay.label": "在线网格衰减",
"settings.map.current.label": "当前地",
"settings.map.animatePaths.label": "活动路径动画",
"settings.map.transparency.label": "设置本窗口透明度",
"settings.map.QSXPath.width.label": "路径宽度",
"settings.map.QSXPath.color.label": "路径颜色",
"settings.map.QRZPath.width.label": "路径宽度",
"settings.map.QRZPath.color.label": "路径颜色",
"settings.map.GraylineDarkness.label": "灰线明暗度",
"settings.map.Brightness.label": "亮度",
"settings.map.MergeAward.label": "合并奖状图层",
"settings.map.FitMapToQRZ.label": "使地图适合用于",
"settings.map.CQHighlight.label": "突出显示",
"settings.map.RXSpotPath.color.label": "",
"settings.map.RXSpotPath.color.default": "调色",
"settings.map.RXSpotPath.enable.label": "路径",
"settings.map.RXSpotPath.width.label": "路径宽",
"settings.map.AutoNight.enable.label": "自动夜间地图",
"settings.map.NightMap.select.label": "更改地图",
"settings.map.NightQSXPath.color.label": "夜间QSX路径颜色",
"settings.map.NightQRZPath.color.label": "夜间QRZ路径颜色",
"settings.map.NightRXSpot.color.label": "夜间PSK-Spot颜色",
"settings.map.NightRXSpot.color.default": "调色",
"settings.map.NightBrightness.label": "夜间亮度",
"settings.logging.tableheader.result": "源/同步",
"settings.logging.gridtracker.source": "",
"settings.logging.gridtracker.details": "",
"settings.logging.LocalFiles.details.add": "增加文件",
"settings.logging.LocalFiles.details.noFiles": "未选择文件",
"settings.logging.PSKReporter.details": "小时历史纪录",
"settings.logging.QRZcom.details.apikey": "QRZ.com",
"settings.logging.QRZcom.test.button": "测试",
"settings.logging.ClubLog.details.email": "CubLog",
"settings.logging.ClubLog.test.button": "测试",
"settings.logging.HRDLogNet.source": "",
"settings.logging.HRDLogNet.details.help.label": "",
"settings.logging.HRDLogNet.test.button": "测试",
"settings.logging.CloudLog.source": "",
"settings.logging.CloudLog.test.button": "测试",
"settings.logging.eQSLcc.source": "",
"settings.logging.eQSLcc.details.QTHnick": "",
"settings.logging.eQSLcc.test.button": "测试",
"settings.logging.LoTW.details.login": "LotW",
"settings.logging.LoTW.details.station": "TQSL 路径",
"settings.logging.LoTW.test.TQSLButton": "测试下载",
"settings.logging.N1MM.source": "",
"settings.logging.N1MM.details.IP": "",
"settings.logging.Log4OM.source": "",
"settings.logging.Log4OM.details.IP": "",
"settings.logging.N3FJP.source": "日志",
"settings.logging.N3FJP.details.IP": "",
"settings.logging.DXKeeper.source": "",
"settings.logging.DXKeeper.details.IP": "",
"settings.logging.HRDLogbook.source": "",
"settings.logging.HRDLogbook.details.IP": "",
"settings.callroster.AlwaysOnTop.label": "窗口总是在最上层",
"settings.callroster.MaxAge.label": "呼叫列表最长时间",
"settings.callroster.MultiRig.HaltTx.label": "在所有其他情况下停止发射",
"settings.callroster.MultiRig.label": "当QSO回答",
"settings.callroster.MultiRig.SwitchView.label": "将显示切换到传输实例",
"settings.callroster.AudioAlert.label": "开启声音警报 <b>新渴望",
"settings.callroster.AudioAlert.MediaFile": "1文本朗读",
"settings.alerts.AudioAlert.label": "声音警报",
"settings.alerts.AudioAlert.Reference.label": "日志文件参考",
"settings.alerts.AudioAlert.Reference.anyBandAnyDigi": "0当前波段及模式",
"settings.alerts.AudioAlert.Header.Value": "启用",
"settings.alerts.AudioAlert.Status.confirmed": "呼号",
"settings.alerts.AudioAlert.Notify.MediaFile": "1文本朗读",
"settings.alerts.AudioAlert.Exceptions.label": "例外情况",
"settings.alerts.AudioAlert.Exceptions.CQOnly": " 仅限CQ",
"settings.alerts.AudioAlert.Exceptions.ReqGrid": "需要网格",
"settings.alerts.AudioAlert.Exceptions.NotMyDXCC": "不是我的DXCC",
"settings.alerts.AudioAlert.Exceptions.OnlyMyDXCC": "仅限我的DXCC",
"settings.alerts.AudioAlert.Exceptions.NoRoundUp": "不要摘要",
"settings.alerts.AudioAlert.Exceptions.OnlyRoundUp": "仅限摘要",
"settings.alerts.AudioAlert.Exceptions.UsesLoTW": "使用LoTW",
"settings.alerts.AudioAlert.Exceptions.UsesEQSL": "使用eQSL",
"settings.alerts.CustomAlerts.label": "自定义警报",
"settings.alerts.CustomAlerts.new.notify.label": "类型",
"settings.alerts.CustomAlerts.new.repeat.label": "重复",
"settings.alerts.CustomAlerts.new.type.QRZ": "0呼号 (准确",
"settings.alerts.CustomAlerts.new.notify.mapcenter": "1文本朗读",
"settings.alerts.CustomAlerts.new.repeat.never": "2直到删除",
"settings.alerts.CustomAlerts.new.addButton": "增加",
"settings.OAMS.message.enable.label": "启用信息传递",
"settings.OAMS.spotting.enable.label": "通过离线信息网络发送和接收Spot报告",
"settings.OAMS.message.newAlert.label": "新信息警报",
"settings.OAMS.message.newAlert.mediaFile": "0无",
"settings.OAMS.message.newAlert.Frequency": "新信息警报出现率",
"settings.OAMS.message.newAlert.60min": "",
"settings.OAMS.message.newAlert.Action": "新信息操作",
"settings.OAMS.message.newAlert.OpenWindow": "0什么都不",
"settings.OAMS.message.awayMode": "离开模",
"settings.OAMS.message.AmAway": "0不要离开",
"settings.OAMS.message.awayText": "离开文本",
"settings.about.AppVersion": "",
"alertPopup.title": "新警报!!!",
"alertPopup.dismiss": "解除",
"updatePopup.newUpdate": "",
"updatePopup.noThanks": "不用了, 谢谢",
"updatePopup.doUpdate": "是的,请更新",
"updatePopup.stopAsking": "停止询问?",
"updatePopup.ok": "",
"bandactivity.title": "波段活动",
"chat.title": "信息",
"chat.notice.agree": "GridTracker 聊天服务不是用HTTPS网络加密或会显示混乱代码. 这意味着它作为它以明文形式发送, 容易受到黑客攻击, 海盗假冒是:国家安全局, 你的妻子, 任何觉得你有趣及关注的人.",
"chat.filter.mode": "所有",
"lookup.title": "呼号信息查询",
"lookup.callsign.button": ">呼号",
"roster.title": "呼叫列",
"roster.controls.less": "打开控件栏",
"roster.controls.logbook.mixBandDigiMode": "日志",
"roster.controls.callsigns.hits": "呼号",
"roster.controls.hunting.wpx": "追寻",
"roster.controls.huntNeed.mixed": "新的",
"roster.controls.huntState.label": "选择区域",
"roster.controls.huntDXCC.label": "选择",
"roster.controls.awardTracker.addButton": "添加奖励",
"roster.controls.awardTracker.new": "新奖项追踪器",
"roster.controls.awardTracker.sponsor": "赞",
"roster.controls.awardTracker.name": "姓名",
"roster.controls.awardTracker.add": "完成",
"roster.secondary.wanted.label": "想要的",
"roster.secondary.wanted.OAMS": "呼",
"COMMENT_GridTracker.html": "",
"statupStatusDiv": "",
"documents.Div2": "",
"documents.Div3": "",
"legend.QSO.hover": "",
"legend.QSL.hover": "",
"legend.QSX.hover": "",
"legend.CQ.hover": "",
"legend.CQDX.hover": "",
"legend.QRZ.hover": "",
"legend.QTH.hover": "",
"legend.WSPR.hover": "",
"MenuButton.hover": "",
"info.frequency.hover": "",
"info.WsjtMode.hover": "",
"info.CurrentTime.hover": "",
"info.DXcall.hover": "",
"info.DXGrid.hover": "",
"info.DXReport.hover": "",
"info.DXCountry.hover": "",
"info.DXDistance.hover": "",
"info.DXAzimuth.hover": "",
"operatingMode.hover": "",
"bandActivity.hover": "",
"quickStats.hover": "",
"quickStats.CallRX.hover": "",
"quickStats.CallRX.label": "",
"quickStats.QSO.hover": "",
"quickStats.QSO.label": "",
"quickStats.DXCCRx.hover": "",
"quickStats.DXCCRx.label": "",
"quickStats.QSL.hover": "",
"quickStats.QSL.label": "",
"quickLoad.clearLive.hover": "",
"quickLoad.clearLog.hover": "",
"quickLoad.loadLog.label": "",
"mapFilter.title.hover": "",
"mapFilter.band.hover": "",
"mapFilter.band.Auto": "",
"mapFilter.band.Mixed": "",
"mapFilter.band.4000m": "",
"mapFilter.band.2200m": "",
"mapFilter.band.630m": "",
"mapFilter.band.160m": "",
"mapFilter.band.80m": "",
"mapFilter.band.60m": "",
"mapFilter.band.40m": "",
"mapFilter.band.30m": "",
"mapFilter.band.20m": "",
"mapFilter.band.17m": "",
"mapFilter.band.15m": "",
"mapFilter.band.12m": "",
"mapFilter.band.11m": "",
"mapFilter.band.10m": "",
"mapFilter.band.6m": "",
"mapFilter.band.4m": "",
"mapFilter.band.2m": "",
"mapFilter.band.125cm": "",
"mapFilter.band.70cm": "",
"mapFilter.band.23cm": "",
"mapFilter.mode.hover": "",
"mapFilter.mode.Auto": "",
"mapFilter.mode.Mixed": "",
"mapFilter.mode.Digital": "",
"mapFilter.prop.hover": "",
"mapFilter.prop.Mixed": "",
"mapFilter.prop.Unknown": "",
"mapFilter.prop.AircraftScatter": "",
"mapFilter.prop.AuroraE": "",
"mapFilter.prop.Aurora": "",
"mapFilter.prop.BackScatter": "",
"mapFilter.prop.EchoLink": "",
"mapFilter.prop.EME": "",
"mapFilter.prop.SporadicE": "",
"mapFilter.prop.F2Reflection": "",
"mapFilter.prop.FieldAlignedIregularities": "",
"mapFilter.prop.InternetAssist": "",
"mapFilter.prop.Ionscatter": "",
"mapFilter.prop.IRLP": "",
"mapFilter.prop.MeteorScatter": "",
"mapFilter.prop.Repeater": "",
"mapFilter.prop.RainScatter": "",
"mapFilter.prop.Satellite": "",
"mapFilter.prop.TransEquatorial": "",
"mapFilter.data.Logbook": "",
"mapFilter.data.Live": "",
"controlPanel.CallRoster.hover": "",
"controlPanel.PushPin.hover": "",
"controlPanel.Lookup.hover": "",
"controlPanel.Stats.hover": "",
"controlPanel.Offline.hover": "",
"controlPanel.Grayline.hover": "",
"controlPanel.MapLegend.hover": "",
"controlPanel.Share.hover": "",
"controlPanel.Help.hover": "",
"controlPanel.Trophy.hover": "",
"controlPanel.Lightening.hover": "",
"controlPanel.Moon.hover": "",
"controlPanel.MaidenheadWidth.hover": "",
"controlPanel.Settings.hover": "",
"controlPanel.LoadADIF.hover": "",
"controlPanel.CurrentCNDX.hover": "",
"controlPanel.DonateMoney.hover": "",
"controlPanel.AudioMute.hover": "",
"controlPanel.Spots.hover": "",
"controlPanel.PSK24.hover": "",
"controlPanel.QRZ.hover": "",
"controlPanel.LOTW.hover": "",
"controlPanel.ClubLog.hover": "",
"controlPanel.LocalAIDF.hover": "",
"controlPanel.Timezone.hover": "",
"controlPanel.Radar.hover": "",
"controlPanel.AllGrids.hover": "",
"controlPanel.GTFlags.hover": "",
"controlPanel.Chat.hover": "",
"settings.General.label": "",
"settings.Lookups.label": "",
"settings.Audio.label": "",
"settings.Map.label": "",
"settings.Grids.label": "",
"settings.Logging.label": "",
"settings.Alerts.label": "",
"settings.CallRoster.label": "",
"settings.OAMS.label": "",
"settings.Logbook.label": "",
"settings.Update.label": "",
"settings.About.label": "",
"settings.general.AppStatus.status": "",
"settings.general.Distance.km": "",
"settings.general.Distance.mi": "",
"settings.general.Distance.nm": "",
"settings.general.Language.label": "",
"settings.lookup.Callook": "",
"settings.lookup.HamQTH": "",
"settings.lookup.QRZcom": "",
"settings.lookup.Password.label": "",
"settings.lookup.AddData.hover": "",
"settings.lookup.AddGrid.hover": "",
"settings.lookup.OpenOnTx.hover": "",
"settings.lookup.CloseOnLog.hover": "",
"settings.lookup.CallookFirst.hover": "",
"settings.lookup.Databases.header": "",
"settings.lookup.Enabled.header": "",
"settings.lookup.LastDwnld.header": "",
"settings.lookup.db.ULS": "",
"settings.lookup.db.LoTW": "",
"settings.lookup.db.eQSL": "",
"settings.lookup.db.OQRS": "",
"settings.audio.Speech.Phonetics.hover": "",
"settings.audio.lighteningAlert.hover": "",
"settings.audio.lighteningAlert.none": "",
"settings.audio.lighteningAlert.short": "",
"settings.audio.lighteningAlert.long": "",
"settings.logbook.callsigns.hover": "",
"settings.logbook.date.hover": "",
"settings.logbook.apply.hover": "",
"settings.logbook.apply.label": "",
"settings.grids.reset.hover": "",
"settings.grids.spotsoverGrids.hover": "",
"settings.grids.splitQSL.hover": "",
"settings.grids.AutoMouseOver.hover": "",
"settings.map.current.hover": "",
"settings.map.animatePaths.hover": "",
"settings.map.animatePaths.speed": "",
"settings.map.MergeAward.hover": "",
"settings.map.FitMapToQRZ.hover": "",
"settings.map.CQHighlight.hover": "",
"settings.map.MissingGrid.label": "",
"settings.map.MissingGrid.hover": "",
"settings.map.RXSpotPath.enable.hover": "",
"settings.map.AutoNight.enable.hover": "",
"settings.map.NightMap.select.hover": "",
"settings.logging.tableheader.source": "",
"settings.logging.tableheader.menu": "",
"settings.logging.tableheader.startup": "",
"settings.logging.tableheader.log": "",
"settings.logging.tableheader.details": "",
"settings.logging.tableheader.test": "",
"settings.logging.LocalFiles.source": "",
"settings.logging.PSKReporter.source": "",
"settings.logging.QRZcom.source": "",
"settings.logging.ClubLog.source": "",
"settings.logging.ClubLog.details.callsign": "",
"settings.logging.ClubLog.details.password": "",
"settings.logging.HRDLogNet.details.callsign": "",
"settings.logging.HRDLogNet.details.upcode": "",
"settings.logging.HRDLogNet.details.help.hover": "",
"settings.logging.CloudLog.details.URL": "",
"settings.logging.CloudLog.details.API": "",
"settings.logging.eQSLcc.details.user": "",
"settings.logging.eQSLcc.details.password": "",
"settings.logging.LoTW.source": "",
"settings.logging.LoTW.details.password": "",
"settings.logging.LoTW.details.TQSLPath": "",
"settings.logging.LoTW.details.TQSLPass": "",
"settings.logging.LoTW.test.downloadButton": "",
"settings.logging.N1MM.details.Port": "",
"settings.logging.Log4OM.details.Port": "",
"settings.logging.N3FJP.details.Port": "",
"settings.logging.DXKeeper.details.Port": "",
"settings.logging.HRDLogbook.details.Port": "",
"settings.callroster.AlwaysOnTop.hover": "",
"settings.callroster.AudioAlert.hover": "",
"settings.callroster.AudioAlert.TextToSpeech": "",
"settings.alerts.AudioAlert.Reference.hover": "",
"settings.alerts.AudioAlert.Reference.currentBandAndMode": "",
"settings.alerts.AudioAlert.Reference.currentBandAnyMode": "",
"settings.alerts.AudioAlert.Reference.currentBandAnyDigi": "",
"settings.alerts.AudioAlert.Reference.currentModeAnyBand": "",
"settings.alerts.AudioAlert.Reference.anyBandAnyMode": "",
"settings.alerts.AudioAlert.Header.Enable": "",
"settings.alerts.AudioAlert.Header.Status": "",
"settings.alerts.AudioAlert.Header.Notify": "",
"settings.alerts.AudioAlert.Types.Callsign": "",
"settings.alerts.AudioAlert.Types.Grid": "",
"settings.alerts.AudioAlert.Types.DXCC": "",
"settings.alerts.AudioAlert.Types.CQZone": "",
"settings.alerts.AudioAlert.Types.ITUZone": "",
"settings.alerts.AudioAlert.Types.USStates": "",
"settings.alerts.AudioAlert.Status.worked": "",
"settings.alerts.AudioAlert.Notify.TextToSpeech": "",
"settings.alerts.AudioAlert.Exceptions.MinDB": "",
"settings.alerts.AudioAlert.Exceptions.MaxDT": "",
"settings.alerts.AudioAlert.Exceptions.MinFreq": "",
"settings.alerts.AudioAlert.Exceptions.MaxFreq": "",
"settings.alerts.CustomAlerts.new.type.label": "",
"settings.alerts.CustomAlerts.new.value.label": "",
"settings.alerts.CustomAlerts.new.type.callsign.exact": "",
"settings.alerts.CustomAlerts.new.type.callsign.partial": "",
"settings.alerts.CustomAlerts.new.type.callsign.regex": "",
"settings.alerts.CustomAlerts.new.type.gridsquare": "",
"settings.alerts.CustomAlerts.new.notify.textToSpeech": "",
"settings.alerts.CustomAlerts.new.notify.mediaFile": "",
"settings.alerts.CustomAlerts.new.notify.visual": "",
"settings.alerts.CustomAlerts.new.repeat.deleted": "",
"settings.alerts.CustomAlerts.new.repeat.exit": "",
"settings.alerts.CustomAlerts.new.repeat.once": "",
"settings.OAMS.message.enable.hover": "",
"settings.OAMS.spotting.enable.hover": "",
"settings.OAMS.message.newAlert.hover": "",
"settings.OAMS.message.newAlert.none": "",
"settings.OAMS.message.newAlert.textToSpeech": "",
"settings.OAMS.message.newAlert.Once": "",
"settings.OAMS.message.newAlert.1min": "",
"settings.OAMS.message.newAlert.3min": "",
"settings.OAMS.message.newAlert.5min": "",
"settings.OAMS.message.newAlert.10min": "",
"settings.OAMS.message.newAlert.15min": "",
"settings.OAMS.message.newAlert.30min": "",
"settings.OAMS.message.newAlert.Nothing": "",
"settings.OAMS.message.NotAway": "",
"settings.about.Brief": "",
"settings.about.FeatureList1": "",
"settings.about.FeatureList2": "",
"settings.about.FeatureList3": "",
"settings.about.FeatureList4": "",
"settings.about.FeatureList5": "",
"settings.about.HomepageLink": "",
"settings.about.Copyright": "",
"updatePopup.noUpdate": "",
"COMMENT_gt_bandactivity.html": "",
"bandactivity.noData": "",
"COMMENT_gt_chat.html": "",
"chat.resume": "",
"chat.ended": "",
"chat.notAvail": "",
"chat.noHistory": "",
"chat.notice.para1": "",
"chat.notice.para2": "",
"chat.notice.para3": "",
"chat.notice.para4": "",
"chat.filter.band": "",
"chat.stationCount": "",
"COMMENT_gt_conditions.html": "",
"conditions.title": "",
"COMMENT_gt_lookup.html": "",
"lookup.callsign.label": "",
"lookup.noinfo": "",
"COMMENT_gt_popup.html": "",
"popup.title": "",
"COMMENT_gt_roster.html": "",
"roster.haltTX": "",
"roster.controls.more": "",
"roster.controls.fewer": "",
"roster.controls.logbook.label": "",
"roster.controls.logbook.awardTracker": "",
"roster.controls.logbook.liveBandMode": "",
"roster.controls.logbook.liveBandMixMode": "",
"roster.controls.logbook.liveBandDigiMode": "",
"roster.controls.logbook.mixBandLiveMode": "",
"roster.controls.logbook.mixBandMode": "",
"roster.controls.callsigns.label": "",
"roster.controls.callsigns.worked": "",
"roster.controls.callsigns.confirmed": "",
"roster.controls.callsigns.all": "",
"roster.controls.hunting.label": "",
"roster.controls.hunting.callsign": "",
"roster.controls.hunting.grid": "",
"roster.controls.hunting.dxcc": "",
"roster.controls.hunting.dxccSingle": "",
"roster.controls.hunting.cqZone": "",
"roster.controls.hunting.ituZone": "",
"roster.controls.hunting.usStates": "",
"roster.controls.hunting.usState": "",
"roster.controls.huntNeed.worked": "",
"roster.controls.huntNeed.confirmed": "",
"roster.secondary.wanted.callsign": "",
"roster.secondary.wanted.grid": "",
"roster.secondary.wanted.dxcc": "",
"roster.secodnary.wanted.qrz": "",
"roster.secondary.wanted.wpx": "",
"roster.secondary.wanted.pota": "",
"roster.secondary.wanted.cqzone": "",
"roster.secondary.wanted.ituzone": "",
"roster.secondary.wanted.state": "",
"roster.secondary.wanted.county": "",
"roster.secondary.wanted": "",
"roster.secondary.exceptions.label": "",
"roster.secondary.exceptions.cqOnly": "",
"roster.secondary.exceptions.hasGrid": "",
"roster.secondary.exceptions.minDB": "",
"roster.secondary.exceptions.maxDT": "",
"roster.secondary.exceptions.minFreq": "",
"roster.secondary.exceptions.maxFreq": "",
"roster.secondary.exceptions.usesLoTW": "",
"roster.secondary.exceptions.spottedMe": "",
"roster.secondary.execptions.noMyDXCC": "",
"roster.secondary.execptions.onlyMyDXCC": "",
"roster.secondary.exceptions.useseQSL": "",
"roster.secondary.exceptions.usesOQRS": "",
"roster.secondary.exceptions.allOnlyNew": "",
"roster.secondary.exceptions.noMsg.label": "",
"roster.secondary.exceptions.noMsg.hover": "",
"roster.secondary.exceptions.onlyMsg.label": "",
"roster.secondary.exceptions.onlyMsg.hover": "",
"roster.secondary.excpetions.regex.label": "",
"roster.secondary.exceptions.regex.hover": "",
"roster.secondary.instances.label": "",
"roster.ignoresTable.title": "",
"roster.ignoresTable.close": "",
"COMMENT_gt_stats.html": "",
"stats.title": "",
"stats.tabs.logbook": "",
"stats.tabs.scores": "",
"stats.tabs.DXCCs": "",
"stats.tabs.CQZones": "",
"stats.tabs.ITUZones": "",
"stats.tabs.WASWAC": "",
"stats.tabs.live": "",
"stats.noDecodes": "",
"stats.noDecodes": "No decodes yet",
"COMMENT_adif.js": "",
"adif.TestResult.invalid": "Invalid",
"adif.TestResult.error": "Unknown Error",
"adif.TestResult.passed": "Passed",
"adif.TestResult.response": "Invalid Response",
"adif.TestResult.testing": "Testing",
"adif.NoFiles": "No file(s) selected",
"adif.LoggedN1MM": "Logged to N1MM",
"adif.LoggedLog4OM": "Logged to Log4OM",
"adif.ExceptionInternal": "Exception Internal Log",
"adif.LoggedGTBackup": "Logged to GridTracker backup",
"adif.ExceptionGTBackup": "Exception GridTracker backup",
"adif.ExceptionQRZ": "Exception QRZ Log",
"adif.ExceptionClubLog": "Exception ClubLog Log",
"adif.ExceptionHRDLogNet": "Exception HrdLog.net Log",
"adif.ExceptionCloudLog": "Exception Cloudlog Log",
"adif.LoggedN3FJP": "Logged to N3FJP Log",
"adif.ExceptionN3FJP": "Exception N3FJP Log",
"adif.LoggedDXKeeper": "Logged to DXKeeper",
"adif.ExceptionDXKeeper": "Exception DXKeeper",
"adif.LoggedHRDLogbook": "Logged to HRD Logbook",
"adif.ExceptionHRDLogbook": "Exception HRD Log",
"adif.ExceptionLoTW": "Excpetion LoTW Log",
"adif.ExceptionAlertLog": "Exception Alert Log",
"adif.ExceptionHideLookup": "Expception Hide Lookup",
"adif.BadPassUser": "Bad<br/>Password<br/>or<br/>Nickname",
"adif.UnknownCall": "Unknown<br/>Callsign",
"adif.QTHNickname": "QTH Nickname<br/>Needed",
"adif.UnknownError": "Unknown<br/>Error",
"adif.FaileQSLCreds": "Fail log eQSL.cc (credentials)",
"adif.FaileQSLNick": "Fail log eQSL.cc (nickname)",
"adif.FaileQSLDupe": "Fail log eQSL.cc (dupe)",
"adif.LoggedeQSL": "Logged to eQSL.cc",
"adif.FailedeQSL": "Fail log eQSL.cc (?)",
"adif.Offline": "Currently<br/>offline",
"adif.TestUpload": "Testing Upload",
"adif.ErrorEncountered": "Error encountered",
"adif.InvalidTQSL": "Invalid tqsl executable",
"adif.MissingTQSL": "TrustedQSL not installed",
"adif.TQSLPassword": "TQSL Password missing",
"adif.TQSLStation": "Select Station",
"adif.TQSLFailed": "Fail log to TQSL",
"adif.TQSLLogged": "Logged to TQSL",
"adif.CloudLogAPIKey": "API Key Invalid",
"adif.CloudLogLogged": "Logged to Cloudlog",
"adif.CloudLogFailed": "Fail log to Cloudlog",
"adif.QRZFailedAlert": "Error uploading QSO to QRZ.com",
"adif.QRZFailed": "Fail log to QRZ.com",
"adif.QRZLogged": "Logged to QRZ.com",
"adif.QRZNoResponse": "Error uploading QSO to QRZ.com (No response)",
"adif.ClubLogLogged": "Logged to ClubLog.org",
"adif.HRDLogNetLogged": "Logged to HRDLOG.net",
"adif.HRDLogNetFailed": "Fail log to HRDLOG.net",
"alerts.addNew.Added": "Added",
"alerts.addNew.SelectFile": "Select File!",
"alerts.addNew.InvalidCall": "Invalid Callsign",
"alerts.addnew.Duplicate": "Duplicate!",
"alerts.callsign.speech": "Callsign",
"alerts.callsign.popup": "Seeking",
"alerts.gridsquare.speech": "Grid square",
"alerts.gridsquare.popup": "Gridsquare",
"alerts.QRZ.speech": "Calling",
"alerts.QRZ.popup": "QRZ",
"alerts.AlertPop.Type": "Type",
"alerts.AlertPop.Value": "Value",
"alerts.AlertPop.Notify": "Notify",
"alerts.AlertPop.Repeat": "Repeat",
"alerts.AlertPop.Filename": "Filename",
"alerts.AlertPop.Alerted": "Alerted",
"alerts.AlertPop.LastMessage": "Last Message",
"alerts.AlertPop.When": "When",
"alerts.AlertPop.Yes": "Yes",
"alerts.AlertPop.No": "No",
"alerts.AlertPop.Gathering": "Gathering Alerts",
"alerts.TypesArray.CallExact": "Call (exact)",
"alerts.TypesArray.Grid": "Grid",
"alerts.TypesArray.QRZ": "QRZ",
"alerts.TypesArray.CallPartial": "Call (partial)",
"alerts.TypesArray.CallRegex": "Call (regex)",
"alerts.ValueArray.AudioFile": "Audio File",
"alerts.ValueArray.TextToSpeech": "TTS",
"alerts.ValueArray.PopUp": "PopUp",
"alerts.ValueArray.MapCenter": "Map Center",
"alerts.RepeatArray.No": "No",
"alerts.RepeatArray.Once": "Once",
"alerts.RepeatArray.Inf": "Inf",
"alerts.RepeatArray.Session": "Inf (Session)",
"alerts.Display.Type": "Type",
"alerts.Display.Value": "Value",
"alerts.Display.Notify": "Notify",
"alerts.Display.Repeat": "Repeat",
"alerts.Display.Filename": "Filename",
"alerts.Display.Alerted": "Alerted",
"alerts.Display.LastMessage": "Last Message",
"alerts.Display.When": "When",
"alerts.Display.Reset": "Reset",
"alerts.Display.Delete": "Delete",
"alerts.ClassicWords.callsign": "Call",
"alerts.ClassicWords.grid": "Grid",
"alerts.ClassicWords.DXCC": "DXCC",
"alerts.ClassicWords.CQz": "C-Q Zone",
"alerts.ClassicWords.ITUz": "I-T-U Zone",
"alerts.ClassicWords.State": "State"
}

Plik diff jest za duży Load Diff

Plik diff jest za duży Load Diff

Wyświetl plik

@ -0,0 +1,562 @@
{
"@metadata": {
"authors": [
"The GridTracker Team"
],
"last-updated": "2021-10-11",
"locale": "es",
"message-documentation": "qqq"
},
"COMMENT_GridTracker.html": "",
"appname-title": "GridTracker ${version}",
"appname-sub-title": "An Amteur Radio Companion",
"statupStatusDiv": "Initial Startup",
"documents.Div1": "Your Documents folder (${searchedDocFolder}) could not be located.",
"documents.Div2": "GridTracker can not continue without it.",
"documents.Div3": "Please select a directory so that GridTracker can store important files.",
"legend.title": "Legend",
"legend.QSO.hover": "Grids with worked station(s) by you",
"legend.QSO.label": "QSO",
"legend.QSL.hover": "Grids with confirmed station(s) by you",
"legend.QSL.label": "QSL",
"legend.QSX.hover": "Grids with station(s) communicating with stations other than you",
"legend.QSX.label": "QSX",
"legend.CQ.hover": "Grids with station(s) calling CQ",
"legend.CQ.label": "CQ",
"legend.CQDX.hover": "Grids with station(s) calling CQ DX",
"legend.CQDX.label": "CQ DX",
"legend.QRZ.hover": "Grids with station(s) calling you!",
"legend.QRZ.label": "QRZ",
"legend.QTH.hover": "Your home grid square!",
"legend.QTH.label": "QTH",
"legend.WSPR.hover": "WSPR Stations",
"MenuButton.hover": "Click to hide menu",
"info.frequency.hover": "Frequency (Band)",
"info.WsjtMode.hover": "Mode",
"info.CurrentTime.hover": "Toggle Local / UTC Time",
"info.DXcall.hover": "Who you're calling or last called",
"info.DXGrid.hover": "Their Gridsquare",
"info.DXReport.hover": "Last known SNR",
"info.DXCountry.hover": "DXCC",
"info.DXDistance.hover": "Distance",
"info.DXAzimuth.hover": "Heading",
"operatingMode.hover": "Click to ignore incoming messages",
"bandActivity.hover": "PSK-Reporter band Activity",
"quickStats.hover": "Quck Stats",
"quickStats.CallRX.hover": "Callsigns Heard",
"quickStats.CallRX.label": "Rx Calls",
"quickStats.QSO.hover": "Worked Stations",
"quickStats.QSO.label": "QSO",
"quickStats.DXCCRx.hover": "DXCC Heard",
"quickStats.DXCCRx.label": "Rx DXCC",
"quickStats.QSL.hover": "Show Confirmed List",
"quickStats.QSL.label": "QSL",
"quickLoad.clearLive.hover": "Clear Live Data from GridTracker",
"quickLoad.clearLive.label": "Clear Live",
"quickLoad.clearLog.hover": "Clear or Reload Log Data (does not delete files)",
"quickLoad.clearLog.label": "Clear Log",
"quickLoad.loadLog.label": "Load Log",
"mapFilter.title.hover": "Map View Control Panel",
"mapFilter.title.label": "Map View Filters",
"mapFilter.band.hover": "Select Band (Auto tracks WSJT-X)",
"mapFilter.band.label": "Band",
"mapFilter.band.Auto": "Auto",
"mapFilter.band.Mixed": "Mixed",
"mapFilter.band.4000m": "4000m",
"mapFilter.band.2200m": "2200m",
"mapFilter.band.630m": "630m",
"mapFilter.band.160m": "160m",
"mapFilter.band.80m": "80m",
"mapFilter.band.60m": "60m",
"mapFilter.band.40m": "40m",
"mapFilter.band.30m": "30m",
"mapFilter.band.20m": "20m",
"mapFilter.band.17m": "17m",
"mapFilter.band.15m": "15m",
"mapFilter.band.12m": "12m",
"mapFilter.band.11m": "11m",
"mapFilter.band.10m": "10m",
"mapFilter.band.6m": "6m",
"mapFilter.band.4m": "4m",
"mapFilter.band.2m": "2m",
"mapFilter.band.125cm": "125cm",
"mapFilter.band.70cm": "70cm",
"mapFilter.band.23cm": "23cm",
"mapFilter.band.OOB": "OOB",
"mapFilter.mode.hover": "Select Mode",
"mapFilter.mode.label": "Mode",
"mapFilter.mode.Auto": "Auto",
"mapFilter.mode.Mixed": "Mixed",
"mapFilter.mode.Digital": "Digital",
"mapFilter.mode.Phone": "Phone",
"mapFilter.prop.hover": "Select Propagation Mode",
"mapFilter.prop.label": "Prop",
"mapFilter.prop.Mixed": "Mixed",
"mapFilter.prop.Unknown": "Unknown",
"mapFilter.prop.AircraftScatter": "Aircraft Scatter",
"mapFilter.prop.AuroraE": "Aurora-E",
"mapFilter.prop.Aurora": "Aurora",
"mapFilter.prop.BackScatter": "Back Scatter",
"mapFilter.prop.EchoLink": "EchoLink",
"mapFilter.prop.EME": "Earth-Moon-Earth",
"mapFilter.prop.SporadicE": "Sporadic E",
"mapFilter.prop.F2Reflection": "F2 Reflection",
"mapFilter.prop.FieldAlignedIregularities": "Field Aligned Iregularities",
"mapFilter.prop.InternetAssist": "Internet Assisted",
"mapFilter.prop.Ionscatter": "Ionoscatter",
"mapFilter.prop.IRLP": "IRLP",
"mapFilter.prop.MeteorScatter": "Meteor Scatter",
"mapFilter.prop.Repeater": "Repeater",
"mapFilter.prop.RainScatter": "Rain Scatter",
"mapFilter.prop.Satellite": "Satellite",
"mapFilter.prop.TransEquatorial": "Trans-Equatorial",
"mapFilter.prop.TropoDuct": "Tropospheric Ducting",
"mapFilter.data.label": "Data",
"mapFilter.data.LogLive": "Logbook &amp; Live",
"mapFilter.data.Logbook": "Logbook",
"mapFilter.data.Live": "Live",
"controlPanel.CallRoster.hover": "Open Call Roster",
"controlPanel.PushPin.hover": "Toggle Push-Pin Mode",
"controlPanel.Lookup.hover": "Open Lookup Window",
"controlPanel.Stats.hover": "Show Stats",
"controlPanel.Offline.hover": "Toggle Online/Offline Mode",
"controlPanel.Grayline.hover": "Toggle Grayline",
"controlPanel.MapLegend.hover": "Toggle Map Legend",
"controlPanel.Share.hover": "Share your On-Air Status with other GridTracker users",
"controlPanel.Help.hover": "Toggle Hotkey List",
"controlPanel.Trophy.hover": "Cycle Award Overlays",
"controlPanel.Lightening.hover": "Toggle Lightening Strikes",
"controlPanel.Moon.hover": "Toggle Moon",
"controlPanel.MaidenheadWidth.hover": "Toggle Maidenhead Width",
"controlPanel.Settings.hover": "Toggle Settings Window",
"controlPanel.LoadADIF.hover": "Load ADIF Log",
"controlPanel.CurrentCNDX.hover": "View Current Conditions",
"controlPanel.DonateMoney.hover": "Donate with PayPal",
"controlPanel.AudioMute.hover": "Toggle Audio Mute",
"controlPanel.Spots.hover": "View Spots",
"controlPanel.PSK24.hover": "Your PSK Reporter 24-Hour Report",
"controlPanel.QRZ.hover": "Load log from QRZ.com",
"controlPanel.LOTW.hover": "Load log from Logbook of The World",
"controlPanel.ClubLog.hover": "Load log from ClubLog",
"controlPanel.LocalAIDF.hover": "Load Local ADIF Files",
"controlPanel.Timezone.hover": "Toggle Timezone Layer",
"controlPanel.Radar.hover": "Toggle US Nexrad Radar",
"controlPanel.AllGrids.hover": "Toggle All Grid Overlay",
"controlPanel.GTFlags.hover": "Toggle View GridTracker Users",
"controlPanel.Chat.hover": "Messaging Window",
"settings.General.label": "General",
"settings.Lookups.label": "Lookups",
"settings.Audio.label": "Audio",
"settings.Map.label": "Map",
"settings.Grids.label": "Grids",
"settings.Logging.label": "Logging",
"settings.Alerts.label": "Alerts",
"settings.CallRoster.label": "Call Roster",
"settings.OAMS.label": "OAMS",
"settings.Logbook.label": "Logbook",
"settings.Update.label": "Update",
"settings.About.label": "About",
"settings.general.AppStatus.label": "Application Status",
"settings.general.AppStatus.status": "Neither WSJT-X or JTDX are running",
"settings.general.UDP.Messages.label": "Receive UDP Messages",
"settings.general.UDP.Multicast.label": "Multicast?",
"settings.general.UDP.IP.label": "IP",
"settings.general.UDP.Port.label": "Port",
"settings.general.Fwd.Messages.label1": "Forward UDP Messages",
"settings.general.Fwd.Messages.label2": "e.g. GridTracker on another host",
"settings.general.Fwd.IP.label": "IP",
"settings.general.Fwd.Port.label": "Port",
"settings.general.Fwd.Enabled.label": "Enabled?",
"settings.general.CenterGrid.label": "Center GridSquare",
"settings.general.DistanceUnits.label": "Distance Units",
"settings.general.Distance.km": "Kilometers",
"settings.general.Distance.mi": "Statute Miles",
"settings.general.Distance.nm": "Nautical Miles",
"settings.general.Distance.dg": "Degrees",
"settings.general.DecodeWaterfall.label": "Decode Traffic Waterfall",
"settings.general.CheckNewVersion.label": "Check for new version",
"settings.general.Language.label": "Language",
"settings.general.ClearAllSettings.label": "Clear All Settings!",
"settings.general.ClearSettingSure.label": "Yes, I'm sure!",
"settings.general.ExportSettings.label": "Export Settings",
"settings.general.ImportSettings.label": "Import Settings",
"settings.lookup.label": "Callsign Lookup Service",
"settings.lookup.Callook": "C A L L O O K (US Only)",
"settings.lookup.HamQTH": "HamQTH (Free Login Required)",
"settings.lookup.QRZcom": "QRZ.com (Free and Paid Members Only)",
"settings.lookup.QRZCQ": "QRZCQ.com (Paid Members Only)",
"settings.lookup.Username.label": "Username",
"settings.lookup.Password.label": "Password",
"settings.lookup.QRZTest": "Test",
"settings.lookup.AddData.label": "Add Lookup Data to QSO Log event",
"settings.lookup.AddData.hover": "When finishing a QSO ...\nadd extra data from Lookup service",
"settings.lookup.AddGrid.label": "Add Lookup Grid if QSO Grid Missing",
"settings.lookup.AddGrid.hover": "Add Lookup Grid if QSO Grid Missing",
"settings.lookup.OpenOnTx.label": "Open Lookup on Transmit",
"settings.lookup.OpenOnTx.hover": "Open Lookup Window on Transmit",
"settings.lookup.CloseOnLog.label": "Close Lookup After Logging",
"settings.lookup.CloseOnLog.hover": "Close Lookup Window After Logging",
"settings.lookup.CallookFirst.label": "Use Callook before using other service",
"settings.lookup.CallookFirst.hover": "Use Callook before using other service, Free Callook yields more data then free QRZ.com.",
"settings.lookup.Databases.label": "Callsign Databases",
"settings.lookup.Databases.header": "Database",
"settings.lookup.Enabled.header": "Enabled",
"settings.lookup.LastDwnld.header": "Last Download",
"settings.lookup.Count.header": "Count",
"settings.lookup.db.ULS": "United States ULS",
"settings.lookup.db.LoTW": "Logbook of The World",
"settings.lookup.db.eQSL": "eQSL",
"settings.lookup.db.OQRS": "ClubLog OQRS",
"settings.audio.TextToSpeech.label": "Text-To-Speech Voice",
"settings.audio.Speech.Rate.label": "Speech Rate",
"settings.audio.Speech.Pitch.label": "Speech Pitch",
"settings.audio.Speech.Volume.label": "Speech Volume",
"settings.audio.Speech.Phonetics.label": "Phonetics",
"settings.audio.Speech.Phonetics.hover": "Speak Callsigns and Gridquares phonetically",
"settings.audio.Device.label": "Audio Device",
"settings.audio.File.Volume.label": "File Audio Volume",
"settings.audio.lighteningAlert.label": "Lightening Strike Audio Alert",
"settings.audio.lighteningAlert.hover": "Lightening Strike Audio Alert",
"settings.audio.lighteningAlert.none": "None",
"settings.audio.lighteningAlert.short": "Short",
"settings.audio.lighteningAlert.long": "Long",
"settings.audio.lighteningAlert.voice": "Voice",
"settings.audio.QSOLogEventFile.label": "QSO Log Event Notification",
"settings.logbook.callsigns.hover": "Filter Logbook QSOs to inlcude these Callsigns only (comma seperated)",
"settings.logbook.callsigns.label": "Working Callsign(s)",
"settings.logbook.callsigns.enable": "Enable?",
"settings.logbook.callsigns.callsigns": "Callsign(s)",
"settings.logbook.date.hover": "Filter Logbook QSOs from before this date",
"settings.logbook.date.label": "Working Date",
"settings.logbook.date.enable": "Enable?",
"settings.logbook.apply.hover": "Apply Changes and Re-Import Logbook(s)",
"settings.logbook.apply.label": "Apply Changes",
"settings.grids.reset.title": "Gridsquare Colors",
"settings.grids.reset.hover": "Reset Gridsquare Colors to Defaults",
"settings.grids.reset.label": "Reset Colors",
"settings.grids.QSO.label": "QSO / Worked",
"settings.grids.QSL.label": "QSL / Confirmed",
"settings.grids.QSX.label": "QSX / Station-2-Station",
"settings.grids.CQ.label": "'CQ' Stations",
"settings.grids.CQDX.label": "'CQ DX' Stations",
"settings.grids.QRZ.label": "QRZ / Your Traffic",
"settings.grids.QTH.label": "QTH / Home Gridsquare",
"settings.grids.spotsOverGrids.label": "RX-Spots Over Grids",
"settings.grids.spotsoverGrids.hover": "Place RX Spots over Grid Layer",
"settings.grids.opacity.label": "Grid Opacity",
"settings.grids.splitQSL.label": "Split QSL Grids",
"settings.grids.splitQSL.hover": "Toggle Split QSL Grids with Live Grids",
"settings.grids.AutoMouseOver.label": "Auto Mouseover Grids",
"settings.grids.AutoMouseOver.hover": "Toggle Auto Mouseover Grid Tables",
"settings.grids.liveDecay.label": "Live Grid Decay",
"settings.map.current.label": "Current Map",
"settings.map.current.hover": "Change Map",
"settings.map.animatePaths.label": "Animate Active Paths",
"settings.map.animatePaths.hover": "Toggle Traffic Path Animation",
"settings.map.animatePaths.speed": "Animation Speed",
"settings.map.transparency.label": "Map Settings Transparency",
"settings.map.QSXPath.width.label": "QSX Path Width",
"settings.map.QSXPath.color.label": "QSX Path Color",
"settings.map.QRZPath.width.label": "QRZ Path Width",
"settings.map.QRZPath.color.label": "QRZ Path Color",
"settings.map.GraylineDarkness.label": "Grayline Darkness",
"settings.map.Brightness.label": "Brightness",
"settings.map.MergeAward.label": "Merge Award Overlay",
"settings.map.MergeAward.hover": "Toggle Merge Award Overlay",
"settings.map.FitMapToQRZ.label": "Fit Map to QRZ",
"settings.map.FitMapToQRZ.hover": "Toggle Fit Map to QRZ",
"settings.map.CQHighlight.label": "'CQ' Highlighting",
"settings.map.CQHighlight.hover": "Toggle 'CQ XX' Highlighting",
"settings.map.MissingGrid.label": "QRZ Missing Grid\nDXCC Fallback",
"settings.map.MissingGrid.hover": "If a station grid not know use center of DXCC",
"settings.map.RXSpotPath.color.label": "RX Spot Color",
"settings.map.RXSpotPath.color.default": "PSK-Reporter Palette",
"settings.map.RXSpotPath.enable.label": "RX Spot Paths",
"settings.map.RXSpotPath.enable.hover": "Toggle flight pathes to spots",
"settings.map.RXSpotPath.width.label": "RX Spot Path Width",
"settings.map.AutoNight.enable.label": "Auto Night Map",
"settings.map.AutoNight.enable.hover": "Toggle Automatic Night Map Switching",
"settings.map.NightMap.select.label": "Night Map",
"settings.map.NightMap.select.hover": "Change Map",
"settings.map.NightQSXPath.color.label": "Night QSX Path Color",
"settings.map.NightQRZPath.color.label": "Night QRZ Path Color",
"settings.map.NightRXSpot.color.label": "Night RX Spot Path Color",
"settings.map.NightRXSpot.color.default": "PSK-Reporter Palette",
"settings.map.NightBrightness.label": "Night Brightness",
"settings.logging.tableheader.source": "Source/Sync",
"settings.logging.tableheader.menu": "Menu?",
"settings.logging.tableheader.startup": "Startup?",
"settings.logging.tableheader.log": "Log?",
"settings.logging.tableheader.details": "Details",
"settings.logging.tableheader.test": "Test",
"settings.logging.tableheader.result": "Result",
"settings.logging.gridtracker.source": "GridTracker",
"settings.logging.gridtracker.details": "GridTracker QSO Logfile",
"settings.logging.LocalFiles.source": "Local File(s)",
"settings.logging.LocalFiles.details.add": "Add File",
"settings.logging.LocalFiles.details.noFiles": "No file(s) selected",
"settings.logging.PSKReporter.source": "PSK-Reporter",
"settings.logging.PSKReporter.details": "24 Hour History",
"settings.logging.QRZcom.source": "QRZ.com",
"settings.logging.QRZcom.details.apikey": "API Key",
"settings.logging.QRZcom.test.button": "Test",
"settings.logging.ClubLog.source": "ClubLog",
"settings.logging.ClubLog.details.callsign": "Callsign",
"settings.logging.ClubLog.details.password": "Password",
"settings.logging.ClubLog.details.email": "Email",
"settings.logging.ClubLog.test.button": "Test",
"settings.logging.HRDLogNet.source": "HRDLOG.net",
"settings.logging.HRDLogNet.details.callsign": "Callsign",
"settings.logging.HRDLogNet.details.upcode": "Upload Code",
"settings.logging.HRDLogNet.details.help.label": "*** How to get upload code ***",
"settings.logging.HRDLogNet.details.help.hover": "Click to learn how to get upload code",
"settings.logging.HRDLogNet.test.button": "Test",
"settings.logging.CloudLog.source": "CloudLog",
"settings.logging.CloudLog.details.URL": "URL",
"settings.logging.CloudLog.details.API": "API Key",
"settings.logging.CloudLog.test.button": "Test",
"settings.logging.eQSLcc.source": "eQSL.cc",
"settings.logging.eQSLcc.details.user": "User",
"settings.logging.eQSLcc.details.password": "Password",
"settings.logging.eQSLcc.details.QTHnick": "QTH Nickname",
"settings.logging.eQSLcc.test.button": "Test",
"settings.logging.LoTW.source": "LoTW",
"settings.logging.LoTW.details.login": "Login",
"settings.logging.LoTW.details.password": "Password",
"settings.logging.LoTW.details.TQSLPath": "TQSL Path",
"settings.logging.LoTW.details.TQSLPass": "TQSL Password",
"settings.logging.LoTW.details.station": "Station Name",
"settings.logging.LoTW.test.downloadButton":"Test Download",
"settings.logging.LoTW.test.TQSLButton": "Test TQSL",
"settings.logging.N1MM.source": "N1MM Logger+",
"settings.logging.N1MM.details.IP": "IP",
"settings.logging.N1MM.details.Port": "Port",
"settings.logging.Log4OM.source": "Log4OM",
"settings.logging.Log4OM.details.IP": "IP",
"settings.logging.Log4OM.details.Port": "Port",
"settings.logging.N3FJP.source": "N3FJP Loggers",
"settings.logging.N3FJP.details.IP": "IP",
"settings.logging.N3FJP.details.Port": "Port",
"settings.logging.DXKeeper.source": "DXKeeper",
"settings.logging.DXKeeper.details.IP": "IP",
"settings.logging.DXKeeper.details.Port": "Port",
"settings.logging.HRDLogbook.source": "HRD Logbook",
"settings.logging.HRDLogbook.details.IP": "IP",
"settings.logging.HRDLogbook.details.Port": "Port",
"settings.callroster.AlwaysOnTop.label": "Window Always On Top",
"settings.callroster.AlwaysOnTop.hover": "Keep Call Roster Above Other Windows",
"settings.callroster.MaxAge.label": "Call Roster Max Age",
"settings.callroster.MultiRig.label": "On QSO Reply",
"settings.callroster.MultiRig.HaltTx.label": "Halt Tx On All Other Instances",
"settings.callroster.MultiRig.SwitchView.label": "Switch View to Transmitting Instance",
"settings.callroster.AudioAlert.label": "Audio Alert on New Wanted",
"settings.callroster.AudioAlert.hover": "Alert when new 'Wanted Row(s)' appear in the Call Roster",
"settings.callroster.AudioAlert.TextToSpeech": "Text-To-Speech",
"settings.callroster.AudioAlert.MediaFile": "Media File",
"settings.alerts.AudioAlert.label": "Audio Alerts",
"settings.alerts.AudioAlert.Reference.label": "Refrence",
"settings.alerts.AudioAlert.Reference.hover": "Log file reference",
"settings.alerts.AudioAlert.Reference.currentBandAndMode": "Current Band and Mode",
"settings.alerts.AudioAlert.Reference.currentBandAnyMode": "Current Band, Any Mode",
"settings.alerts.AudioAlert.Reference.currentBandAnyDigi": "Current Band, Any Digital Mode",
"settings.alerts.AudioAlert.Reference.currentModeAnyBand": "Current Mode, Any Band",
"settings.alerts.AudioAlert.Reference.anyBandAnyMode": "Any Band, Any Mode",
"settings.alerts.AudioAlert.Reference.anyBandAnyDigi": "Any Band, Any Digital Mode",
"settings.alerts.AudioAlert.Header.Enable": "Enable",
"settings.alerts.AudioAlert.Header.Status": "Status",
"settings.alerts.AudioAlert.Header.Notify": "Notify",
"settings.alerts.AudioAlert.Header.Value": "Value",
"settings.alerts.AudioAlert.Types.Callsign": "Callsign",
"settings.alerts.AudioAlert.Types.Grid": "Grid",
"settings.alerts.AudioAlert.Types.DXCC": "DXCC",
"settings.alerts.AudioAlert.Types.CQZone": "CQ Zone",
"settings.alerts.AudioAlert.Types.ITUZone": "ITU Zone",
"settings.alerts.AudioAlert.Types.USStates": "US States",
"settings.alerts.AudioAlert.Status.worked": "New",
"settings.alerts.AudioAlert.Status.confirmed": "New+Unconf",
"settings.alerts.AudioAlert.Notify.TextToSpeech": "Text-To-Speech",
"settings.alerts.AudioAlert.Notify.MediaFile": "Media File",
"settings.alerts.AudioAlert.Exceptions.label": "Exceptions",
"settings.alerts.AudioAlert.Exceptions.CQOnly": "CQ Only",
"settings.alerts.AudioAlert.Exceptions.ReqGrid": "Require Grid",
"settings.alerts.AudioAlert.Exceptions.MinDB": "Min dB",
"settings.alerts.AudioAlert.Exceptions.MaxDT": "Max DT",
"settings.alerts.AudioAlert.Exceptions.MinFreq": "Min Freq",
"settings.alerts.AudioAlert.Exceptions.MaxFreq": "Max Freq",
"settings.alerts.AudioAlert.Exceptions.NotMyDXCC": "Not My DXCC",
"settings.alerts.AudioAlert.Exceptions.OnlyMyDXCC": "Only My Dxcc",
"settings.alerts.AudioAlert.Exceptions.NoRoundUp": "No Round-Up",
"settings.alerts.AudioAlert.Exceptions.OnlyRoundUp": "Only Round-Up",
"settings.alerts.AudioAlert.Exceptions.UsesLoTW": "Uses LoTW",
"settings.alerts.AudioAlert.Exceptions.UsesEQSL": "Uses eQSL",
"settings.alerts.CustomAlerts.label": "Custom Alerts",
"settings.alerts.CustomAlerts.new.type.label": "Type",
"settings.alerts.CustomAlerts.new.value.label": "Value",
"settings.alerts.CustomAlerts.new.notify.label": "Notify",
"settings.alerts.CustomAlerts.new.repeat.label": "Repeat",
"settings.alerts.CustomAlerts.new.type.callsign.exact": "Callsign (exact)",
"settings.alerts.CustomAlerts.new.type.callsign.partial": "Callsign (partial)",
"settings.alerts.CustomAlerts.new.type.callsign.regex": "Callsign (regex)",
"settings.alerts.CustomAlerts.new.type.gridsquare": "Gridsquare",
"settings.alerts.CustomAlerts.new.type.QRZ": "QRZ",
"settings.alerts.CustomAlerts.new.notify.textToSpeech": "Text-To-Speech",
"settings.alerts.CustomAlerts.new.notify.mediaFile": "Media File",
"settings.alerts.CustomAlerts.new.notify.visual": "Visual Popup",
"settings.alerts.CustomAlerts.new.notify.mapcenter": "Map Center",
"settings.alerts.CustomAlerts.new.repeat.deleted": "Until Deleted",
"settings.alerts.CustomAlerts.new.repeat.exit": "Until Exit",
"settings.alerts.CustomAlerts.new.repeat.once": "Only Once",
"settings.alerts.CustomAlerts.new.repeat.never": "Never Repeat",
"settings.alerts.CustomAlerts.new.addButton": "ADD",
"settings.OAMS.message.enable.label": "Messaging Enable",
"settings.OAMS.message.enable.hover": "Messaging Enable",
"settings.OAMS.spotting.enable.label": "Spotting Enable",
"settings.OAMS.spotting.enable.hover": "Send and Receivev Spot Reports through the OAMS network",
"settings.OAMS.message.newAlert.label": "New Message Alert",
"settings.OAMS.message.newAlert.hover": "Alert when new messages received.",
"settings.OAMS.message.newAlert.none": "None",
"settings.OAMS.message.newAlert.textToSpeech": "Text-To-Speech",
"settings.OAMS.message.newAlert.mediaFile": "Media File",
"settings.OAMS.message.newAlert.Frequency": "Alert Frequency",
"settings.OAMS.message.newAlert.Once": "Only Once",
"settings.OAMS.message.newAlert.1min": "1 minute",
"settings.OAMS.message.newAlert.3min": "3 minute",
"settings.OAMS.message.newAlert.5min": "5 minute",
"settings.OAMS.message.newAlert.10min": "10 minute",
"settings.OAMS.message.newAlert.15min": "15 minute",
"settings.OAMS.message.newAlert.30min": "30 minute",
"settings.OAMS.message.newAlert.60min": "1 hour",
"settings.OAMS.message.newAlert.Action": "New Message Action",
"settings.OAMS.message.newAlert.Nothing": "Do Nothing",
"settings.OAMS.message.newAlert.OpenWindow": "Open Messaging Window",
"settings.OAMS.message.awayMode": "Away Mode",
"settings.OAMS.message.NotAway": "Not Away",
"settings.OAMS.message.AmAway": "I Am Away",
"settings.OAMS.message.awayText": "Away Text",
"settings.about.AppVersion": "GridTracker ${version}",
"settings.about.Brief": "GridTracker is a warehouse of amateur radio information presented in an easy to use interface",
"settings.about.FeatureList1": "From Live Traffic Decodes",
"settings.about.FeatureList2": "Logbooks",
"settings.about.FeatureList3": "Real-time Spot Reports",
"settings.about.FeatureList4": "Weather",
"settings.about.FeatureList5": "Current Solar Conditions and More!",
"settings.about.HomepageLink": "Learn more at",
"settings.about.Copyright": "Copyright &copy; 2021 GridTracker.org",
"alertPopup.title": "New Alerts!!!",
"alertPopup.dismiss": "DISMISS",
"updatePopup.newUpdate": "GridTracker Updated!",
"updatePopup.noThanks": "NO, Thanks",
"updatePopup.doUpdate": "Yes, Please!",
"updatePopup.stopAsking": "Stop asking?",
"updatePopup.noUpdate": "GridTracker is up to date!",
"updatePopup.ok": "OK",
"COMMENT_gt_bandactivity.html": "",
"bandactivity.title": "Band Activity",
"bandactivity.noData": "...no data yet...",
"COMMENT_gt_chat.html": "",
"chat.title": "Off-Air Message Service (OAMS)",
"chat.resume": "Session resumed",
"chat.ended": "Session ended",
"chat.notAvail": "...this session is no longer available...",
"chat.noHistory": "no message history",
"chat.notice.para1": "NOTICE: GridTracker chat is not encrypted or obfuscated beyond HTTPS. This means that it's sent as plaintext that is vulnerable to hackers, pirates, the NSA, your wife, and anyone that thinks you're interesting enough to monitor.",
"chat.notice.para2": "<b>NEVER</b> give passwords, credit card numbers, safe combinations or any personal information that you don't want bad people to know because there are some very bad people out there.",
"chat.notice.para3": "Not us, though. While GridTracker is free, unlike some other free apps, we don't store, save, sell, peek at or otherwise do anything with the chat that would violate your trust. We don't keep logs. We don't save Metadata. We just don't.",
"chat.notice.para4": "Close GridTracker, lose the text. So write anything down you want to save. Because when it's gone, gone is forever.",
"chat.notice.agree": "Click here to acknowledge the above and enable messaging",
"chat.filter.band": "Band:",
"chat.filter.mode": "Mode:",
"chat.stationCount": "Station Count",
"COMMENT_gt_conditions.html": "",
"conditions.title": "Current Conditions",
"COMMENT_gt_lookup.html": "",
"lookup.title": "Callsign Lookup",
"lookup.callsign.label": "Callsign",
"lookup.callsign.button": "Lookup",
"lookup.noinfo": "No Callsign information to display<br />try a lookup!",
"COMMENT_gt_popup.html": "",
"popup.title": "Data Breakout",
"COMMENT_gt_roster.html": "",
"roster.title": "Call Roster",
"roster.haltTX": "Halt TX",
"roster.controls.more": "More Controls",
"roster.controls.fewer": "Fewer Controls",
"roster.controls.logbook.label": "Logbook",
"roster.controls.logbook.awardTracker": "Award Tracker",
"roster.controls.logbook.liveBandMode": "Live Band &amp; Mode",
"roster.controls.logbook.liveBandMixMode": "Live Band, Mix Modes",
"roster.controls.logbook.liveBandDigiMode": "Live Band, Digi Modes",
"roster.controls.logbook.mixBandLiveMode": "Mix Band, Live Mode",
"roster.controls.logbook.mixBandMode": "Mix Band &amp; Modes",
"roster.controls.logbook.mixBandDigiMode": "Mix Band &amp; Digi Modes",
"roster.controls.callsigns.label": "Callsigns",
"roster.controls.callsigns.worked": "New",
"roster.controls.callsigns.confirmed": "New+Unconfirmed",
"roster.controls.callsigns.all": "All Traffic",
"roster.controls.callsigns.hits": "All Traffic/Only Winted",
"roster.controls.hunting.label": "Hunting",
"roster.controls.hunting.callsign": "Callsign",
"roster.controls.hunting.grid": "Grid",
"roster.controls.hunting.dxcc": "DXCC",
"roster.controls.hunting.dxccSingle": "DXCC (Single)",
"roster.controls.hunting.cqZone": "CQ Zone",
"roster.controls.hunting.ituZone": "ITU Zone",
"roster.controls.hunting.usStates": "US State (WAS)",
"roster.controls.hunting.usState": "US State (Single)",
"roster.controls.hunting.wpx": "Prefix (WPX)",
"roster.controls.huntNeed.worked": "New",
"roster.controls.huntNeed.confirmed": "New+Unconfirmed",
"roster.controls.huntNeed.mixed": "Mixed",
"roster.controls.huntState.label": "Select Territory",
"roster.controls.huntDXCC.label": "Select DXCC",
"roster.controls.awardTracker.new": "New Award Tracker",
"roster.controls.awardTracker.sponsor": "Sponosor",
"roster.controls.awardTracker.name": "Name",
"roster.controls.awardTracker.add": "Done",
"roster.secondary.wanted.label": "Wanted",
"roster.secondary.wanted.callsign": "Callsign",
"roster.secondary.wanted.grid": "Grid",
"roster.secondary.wanted.dxcc": "DXCC",
"roster.secodnary.wanted.qrz": "QRZ",
"roster.secondary.wanted.wpx": "WPX",
"roster.secondary.wanted.pota": "POTA",
"roster.secondary.wanted.OAMS": "OAMS",
"roster.secondary.wanted.cqzone": "CQz",
"roster.secondary.wanted.ituzone": "ITUz",
"roster.secondary.wanted.state": "State",
"roster.secondary.wanted.county": "County",
"roster.secondary.wanted cont": "Cont",
"roster.secondary.exceptions.label": "Exceptions",
"roster.secondary.exceptions.cqOnly": "CQ Only",
"roster.secondary.exceptions.hasGrid": "Has Grid",
"roster.secondary.exceptions.minDB": "Min dB",
"roster.secondary.exceptions.maxDT": "Max DT",
"roster.secondary.exceptions.minFreq": "Min Freq",
"roster.secondary.exceptions.maxFreq": "Max Freq",
"roster.secondary.exceptions.usesLoTW": "Uses LoTW",
"roster.secondary.exceptions.spottedMe": "Spotted Me",
"roster.secondary.execptions.noMyDXCC": "Not My Dxcc",
"roster.secondary.execptions.onlyMyDXCC": "Only My DXCC",
"roster.secondary.exceptions.useseQSL":" Uses eQSL",
"roster.secondary.exceptions.usesOQRS": "Uses OQRS",
"roster.secondary.exceptions.allOnlyNew": "Only New Calls",
"roster.secondary.exceptions.noMsg.label": "No",
"roster.secondary.exceptions.noMsg.hover": "No Decodes Containing...",
"roster.secondary.exceptions.onlyMsg.label": "Only",
"roster.secondary.exceptions.onlyMsg.hover": "Only Decodes Containing...",
"roster.secondary.excpetions.regex.label": "Regex",
"roster.secondary.exceptions.regex.hover": "Callsign Regular Expression",
"roster.secondary.instances.label": "Instances",
"roster.ignoresTable.title": "Callsign, CQ and DXCC Ignores",
"roster.ignoresTable.close": "Close",
"COMMENT_gt_stats.html": "",
"stats.title": "Statistics",
"stats.tabs.logbook": "Logbook",
"stats.tabs.scores": "Scores",
"stats.tabs.DXCCs": "DXCCs",
"stats.tabs.CQZones": "CQ Zones",
"stats.tabs.ITUZones": "ITU Zones",
"stats.tabs.WASWAC": "WAC / WAS",
"stats.tabs.live": "Live",
"stats.noDecodes": "No decodes yet"
}

Wyświetl plik

@ -0,0 +1,54 @@
#!/usr/bin/python3
def readDiff():
with open('patch.diff', encoding='utf-8', errors="ignore") as diff_file:
lines = diff_file.readlines()
# sample lines
# - <div id="startupStatusDiv" data-i18n="startupStatusDiv">Initial Startup</div>
# + <div id="startupStatusDiv">初始化启动</div>
json_output = open("cn.json", "a")
for index, line in enumerate(lines):
if line.startswith("-") and lines[index + 1].startswith("+") and 'data-i18n' in line:
# remove prefix '-'
sanitized_line = line[1:]
print(f"sanitized_line: {sanitized_line}")
# remove prefix '+'
sanitized_next_line = lines[index + 1][1:]
print(f"sanitized_next_line: {sanitized_next_line}")
key_start = sanitized_line.index('data-i18n') + 11
key_to_end = sanitized_line[key_start:]
key_end = key_to_end.index('"')
i18n_key = sanitized_line[key_start: key_start + key_end]
print(f"i18n_key: {i18n_key}")
# remove data-i18n-tag
i18n_removed_line = f"{sanitized_line[0: sanitized_line.index('data-i18n') -1]}{sanitized_line[key_start + key_end + 1:]}"
print(i18n_removed_line)
translated_phrase = ''
# this will output string with ending tag like this: 初始化启动</div>
for line_index, char in enumerate(sanitized_next_line):
if len(i18n_removed_line) > line_index and char == i18n_removed_line[line_index]:
continue
else:
translated_phrase = f"{translated_phrase}{char}"
print(f"translated_phrase: {translated_phrase}")
# now remove closing tag
if translated_phrase:
for line_index, char in enumerate(i18n_removed_line[::-1]):
if len(sanitized_next_line) > line_index and char == sanitized_next_line[::-1][line_index]:
translated_phrase = translated_phrase[:-1]
else:
break
print(f"translated_phrase: {translated_phrase}")
# partial json: "legend.title": "Legend",
json_output.write(f'"{i18n_key}": "{translated_phrase}",\n')
def main():
readDiff()
if __name__ == "__main__":
main()

Plik diff jest za duży Load Diff

Plik diff jest za duży Load Diff

Wyświetl plik

@ -0,0 +1,685 @@
/* eslint-disable no-tabs */
/**
* cldrpluralparser.js
* A parser engine for CLDR plural rules.
*
* Copyright 2012-2014 Santhosh Thottingal and other contributors
* Released under the MIT license
* http://opensource.org/licenses/MIT
*
* @source https://github.com/santhoshtr/CLDRPluralRuleParser
* @author Santhosh Thottingal <santhosh.thottingal@gmail.com>
* @author Timo Tijhof
* @author Amir Aharoni
*/
/**
* Evaluates a plural rule in CLDR syntax for a number
* @param {string} rule
* @param {integer} number
* @return {boolean} true if evaluation passed, false if evaluation failed.
*/
// UMD returnExports https://github.com/umdjs/umd/blob/master/returnExports.js
(function(root, factory)
{
if (typeof define === "function" && define.amd)
{
// AMD. Register as an anonymous module.
define(factory);
}
else if (typeof exports === "object")
{
// Node. Does not work with strict CommonJS, but
// only CommonJS-like environments that support module.exports,
// like Node.
module.exports = factory();
}
else
{
// Browser globals (root is window)
root.pluralRuleParser = factory();
}
}(this, function()
{
function pluralRuleParser(rule, number)
{
"use strict";
/*
Syntax: see http://unicode.org/reports/tr35/#Language_Plural_Rules
-----------------------------------------------------------------
condition = and_condition ('or' and_condition)*
('@integer' samples)?
('@decimal' samples)?
and_condition = relation ('and' relation)*
relation = is_relation | in_relation | within_relation
is_relation = expr 'is' ('not')? value
in_relation = expr (('not')? 'in' | '=' | '!=') range_list
within_relation = expr ('not')? 'within' range_list
expr = operand (('mod' | '%') value)?
operand = 'n' | 'i' | 'f' | 't' | 'v' | 'w'
range_list = (range | value) (',' range_list)*
value = digit+
digit = 0|1|2|3|4|5|6|7|8|9
range = value'..'value
samples = sampleRange (',' sampleRange)* (',' ('…'|'...'))?
sampleRange = decimalValue '~' decimalValue
decimalValue = value ('.' value)?
*/
// We don't evaluate the samples section of the rule. Ignore it.
rule = rule.split("@")[0].replace(/^\s*/, "").replace(/\s*$/, "");
if (!rule.length)
{
// Empty rule or 'other' rule.
return true;
}
// Indicates the current position in the rule as we parse through it.
// Shared among all parsing functions below.
var pos = 0,
operand,
expression,
relation,
result,
whitespace = makeRegexParser(/^\s+/),
value = makeRegexParser(/^\d+/),
_n_ = makeStringParser("n"),
_i_ = makeStringParser("i"),
_f_ = makeStringParser("f"),
_t_ = makeStringParser("t"),
_v_ = makeStringParser("v"),
_w_ = makeStringParser("w"),
_is_ = makeStringParser("is"),
_isnot_ = makeStringParser("is not"),
_isnot_sign_ = makeStringParser("!="),
_equal_ = makeStringParser("="),
_mod_ = makeStringParser("mod"),
_percent_ = makeStringParser("%"),
_not_ = makeStringParser("not"),
_in_ = makeStringParser("in"),
_within_ = makeStringParser("within"),
_range_ = makeStringParser(".."),
_comma_ = makeStringParser(","),
_or_ = makeStringParser("or"),
_and_ = makeStringParser("and");
function debug()
{
// console.log.apply(console, arguments);
}
debug("pluralRuleParser", rule, number);
// Try parsers until one works, if none work return null
function choice(parserSyntax)
{
return function()
{
var i, result;
for (i = 0; i < parserSyntax.length; i++)
{
result = parserSyntax[i]();
if (result !== null)
{
return result;
}
}
return null;
};
}
// Try several parserSyntax-es in a row.
// All must succeed; otherwise, return null.
// This is the only eager one.
function sequence(parserSyntax)
{
var i, parserRes,
originalPos = pos,
result = [];
for (i = 0; i < parserSyntax.length; i++)
{
parserRes = parserSyntax[i]();
if (parserRes === null)
{
pos = originalPos;
return null;
}
result.push(parserRes);
}
return result;
}
// Run the same parser over and over until it fails.
// Must succeed a minimum of n times; otherwise, return null.
function nOrMore(n, p)
{
return function()
{
var originalPos = pos,
result = [],
parsed = p();
while (parsed !== null)
{
result.push(parsed);
parsed = p();
}
if (result.length < n)
{
pos = originalPos;
return null;
}
return result;
};
}
// Helpers - just make parserSyntax out of simpler JS builtin types
function makeStringParser(s)
{
var len = s.length;
return function()
{
var result = null;
if (rule.substr(pos, len) === s)
{
result = s;
pos += len;
}
return result;
};
}
function makeRegexParser(regex)
{
return function()
{
var matches = rule.substr(pos).match(regex);
if (matches === null)
{
return null;
}
pos += matches[0].length;
return matches[0];
};
}
/**
* Integer digits of n.
*/
function i()
{
var result = _i_();
if (result === null)
{
debug(" -- failed i", parseInt(number, 10));
return result;
}
result = parseInt(number, 10);
debug(" -- passed i ", result);
return result;
}
/**
* Absolute value of the source number (integer and decimals).
*/
function n()
{
var result = _n_();
if (result === null)
{
debug(" -- failed n ", number);
return result;
}
result = parseFloat(number, 10);
debug(" -- passed n ", result);
return result;
}
/**
* Visible fractional digits in n, with trailing zeros.
*/
function f()
{
var result = _f_();
if (result === null)
{
debug(" -- failed f ", number);
return result;
}
result = (number + ".").split(".")[1] || 0;
debug(" -- passed f ", result);
return result;
}
/**
* Visible fractional digits in n, without trailing zeros.
*/
function t()
{
var result = _t_();
if (result === null)
{
debug(" -- failed t ", number);
return result;
}
result = (number + ".").split(".")[1].replace(/0$/, "") || 0;
debug(" -- passed t ", result);
return result;
}
/**
* Number of visible fraction digits in n, with trailing zeros.
*/
function v()
{
var result = _v_();
if (result === null)
{
debug(" -- failed v ", number);
return result;
}
result = (number + ".").split(".")[1].length || 0;
debug(" -- passed v ", result);
return result;
}
/**
* Number of visible fraction digits in n, without trailing zeros.
*/
function w()
{
var result = _w_();
if (result === null)
{
debug(" -- failed w ", number);
return result;
}
result = (number + ".").split(".")[1].replace(/0$/, "").length || 0;
debug(" -- passed w ", result);
return result;
}
// operand = 'n' | 'i' | 'f' | 't' | 'v' | 'w'
operand = choice([n, i, f, t, v, w]);
// expr = operand (('mod' | '%') value)?
expression = choice([mod, operand]);
function mod()
{
var result = sequence(
[operand, whitespace, choice([_mod_, _percent_]), whitespace, value]
);
if (result === null)
{
debug(" -- failed mod");
return null;
}
debug(" -- passed " + parseInt(result[0], 10) + " " + result[2] + " " + parseInt(result[4], 10));
return parseFloat(result[0]) % parseInt(result[4], 10);
}
function not()
{
var result = sequence([whitespace, _not_]);
if (result === null)
{
debug(" -- failed not");
return null;
}
return result[1];
}
// is_relation = expr 'is' ('not')? value
function is()
{
var result = sequence([expression, whitespace, choice([_is_]), whitespace, value]);
if (result !== null)
{
debug(" -- passed is : " + result[0] + " == " + parseInt(result[4], 10));
return result[0] === parseInt(result[4], 10);
}
debug(" -- failed is");
return null;
}
// is_relation = expr 'is' ('not')? value
function isnot()
{
var result = sequence(
[expression, whitespace, choice([_isnot_, _isnot_sign_]), whitespace, value]
);
if (result !== null)
{
debug(" -- passed isnot: " + result[0] + " != " + parseInt(result[4], 10));
return result[0] !== parseInt(result[4], 10);
}
debug(" -- failed isnot");
return null;
}
function not_in()
{
var i, range_list,
result = sequence([expression, whitespace, _isnot_sign_, whitespace, rangeList]);
if (result !== null)
{
debug(" -- passed not_in: " + result[0] + " != " + result[4]);
range_list = result[4];
for (i = 0; i < range_list.length; i++)
{
if (parseInt(range_list[i], 10) === parseInt(result[0], 10))
{
return false;
}
}
return true;
}
debug(" -- failed not_in");
return null;
}
// range_list = (range | value) (',' range_list)*
function rangeList()
{
var result = sequence([choice([range, value]), nOrMore(0, rangeTail)]),
resultList = [];
if (result !== null)
{
resultList = resultList.concat(result[0]);
if (result[1][0])
{
resultList = resultList.concat(result[1][0]);
}
return resultList;
}
debug(" -- failed rangeList");
return null;
}
function rangeTail()
{
// ',' range_list
var result = sequence([_comma_, rangeList]);
if (result !== null)
{
return result[1];
}
debug(" -- failed rangeTail");
return null;
}
// range = value'..'value
function range()
{
var i, array, left, right,
result = sequence([value, _range_, value]);
if (result !== null)
{
debug(" -- passed range");
array = [];
left = parseInt(result[0], 10);
right = parseInt(result[2], 10);
for (i = left; i <= right; i++)
{
array.push(i);
}
return array;
}
debug(" -- failed range");
return null;
}
function _in()
{
var result, range_list, i;
// in_relation = expr ('not')? 'in' range_list
result = sequence(
[expression, nOrMore(0, not), whitespace, choice([_in_, _equal_]), whitespace, rangeList]
);
if (result !== null)
{
debug(" -- passed _in:" + result);
range_list = result[5];
for (i = 0; i < range_list.length; i++)
{
if (parseInt(range_list[i], 10) === parseFloat(result[0]))
{
return (result[1][0] !== "not");
}
}
return (result[1][0] === "not");
}
debug(" -- failed _in ");
return null;
}
/**
* The difference between "in" and "within" is that
* "in" only includes integers in the specified range,
* while "within" includes all values.
*/
function within()
{
var range_list, result;
// within_relation = expr ('not')? 'within' range_list
result = sequence(
[expression, nOrMore(0, not), whitespace, _within_, whitespace, rangeList]
);
if (result !== null)
{
debug(" -- passed within");
range_list = result[5];
if ((result[0] >= parseInt(range_list[0], 10)) &&
(result[0] < parseInt(range_list[range_list.length - 1], 10)))
{
return (result[1][0] !== "not");
}
return (result[1][0] === "not");
}
debug(" -- failed within ");
return null;
}
// relation = is_relation | in_relation | within_relation
relation = choice([is, not_in, isnot, _in, within]);
// and_condition = relation ('and' relation)*
function and()
{
var i,
result = sequence([relation, nOrMore(0, andTail)]);
if (result)
{
if (!result[0])
{
return false;
}
for (i = 0; i < result[1].length; i++)
{
if (!result[1][i])
{
return false;
}
}
return true;
}
debug(" -- failed and");
return null;
}
// ('and' relation)*
function andTail()
{
var result = sequence([whitespace, _and_, whitespace, relation]);
if (result !== null)
{
debug(" -- passed andTail" + result);
return result[3];
}
debug(" -- failed andTail");
return null;
}
// ('or' and_condition)*
function orTail()
{
var result = sequence([whitespace, _or_, whitespace, and]);
if (result !== null)
{
debug(" -- passed orTail: " + result[3]);
return result[3];
}
debug(" -- failed orTail");
return null;
}
// condition = and_condition ('or' and_condition)*
function condition()
{
var i,
result = sequence([and, nOrMore(0, orTail)]);
if (result)
{
for (i = 0; i < result[1].length; i++)
{
if (result[1][i])
{
return true;
}
}
return result[0];
}
return false;
}
result = condition();
/**
* For success, the pos must have gotten to the end of the rule
* and returned a non-null.
* n.b. This is part of language infrastructure,
* so we do not throw an internationalizable message.
*/
if (result === null)
{
throw new Error("Parse error at position " + pos.toString() + " for rule: " + rule);
}
if (pos !== rule.length)
{
debug("Warning: Rule not parsed completely. Parser stopped at " + rule.substr(0, pos) + " for rule: " + rule);
}
return result;
}
return pluralRuleParser;
}));

Wyświetl plik

@ -108,6 +108,36 @@ function onAdiLoadComplete(adiBuffer, saveAdifFile, adifFileName, newFile)
{
let finalMode = "";
let appLoTW_RXQSO = findAdiField(
activeAdifArray[x],
"APP_LoTW_RXQSO"
);
if (appLoTW_RXQSO != "")
{
let dRXQSO = Date.parse(appLoTW_RXQSO);
let dLastLOTW_QSO = Date.parse(g_adifLogSettings.lastFetch.lotw_qso);
if ((isNaN(dRXQSO) == false) && (isNaN(dLastLOTW_QSO) == false) && (dRXQSO > dLastLOTW_QSO))
{
g_adifLogSettings.lastFetch.lotw_qso = appLoTW_RXQSO;
}
}
let appLoTW_RXQSL = findAdiField(
activeAdifArray[x],
"APP_LoTW_RXQSL"
);
if (appLoTW_RXQSL != "")
{
let dRXQSL = Date.parse(appLoTW_RXQSL);
let dLastLOTW_QSL = Date.parse(g_adifLogSettings.lastFetch.lotw_qsl);
if ((isNaN(dRXQSL) == false) && (isNaN(dLastLOTW_QSL) == false) && (dRXQSL > dLastLOTW_QSL))
{
g_adifLogSettings.lastFetch.lotw_qso = appLoTW_RXQSO;
}
}
if (activeAdifArray[x].length > 3)
{
if (activeAdifLogMode)
@ -737,6 +767,27 @@ function grabLoTWQSL()
"g_isGettingLOTW",
120000
);
// Fetch QSLs
var tQSO = setTimeout(function()
{
if (test == false) lotwLogLoaded = true;
getABuffer(
"https://lotw.arrl.org/lotwuser/lotwreport.adi?login=" +
lotwLogin.value +
"&password=" +
encodeURIComponent(lotwPassword.value) +
"&qso_query=1&qso_qsl=yes&qso_qsldetail=yes&qso_withown=yes" +
lastQSLDateString,
lotwCallback,
test,
"https",
443,
lotwLogImg,
"g_isGettingLOTW",
120000
);
}, 10000);
}
}

Wyświetl plik

@ -357,7 +357,7 @@ function addNewAlert()
if (alertMediaSelect.value == "none")
{
valid = false;
error = "Select File!";
error = $.i18n("alerts.addNew.SelectFile");
}
else
{

Wyświetl plik

@ -0,0 +1,106 @@
table,
th,
td,
body,
input {
color: #fff;
white-space: nowrap;
font-family: Sans-Serif;
font-size: 13px;
text-align: auto;
}
.boxDisplay {
margin: 1px;
padding: 2px;
border-width: 2px;
border-color: #aaa;
border-style: inset;
vertical-align: top;
-webkit-border-radius: 4px;
}
textarea {
width: 100%;
resize: none;
font-size: 15px;
}
.self {
color: #ffff00;
font-weight: bold;
}
.them {
color: #00ffff;
font-weight: bold;
}
.system {
color: #ff0000;
font-weight: bold;
}
.when {
color: #777777;
font-size: 12px;
}
.msgText {
color: #eeeeee;
font-size: 15px;
}
.msgTextUnicode {
color: #eeeeee;
font-size: 15px;
}
body {
background-image: url(img/gridtracker10.png);
background-repeat: no-repeat;
background-attachment: fixed;
background-position: center;
}
#callsign {
color: #00ffff;
font-weight: bold;
}
#country,
#dxcc {
color: #ffff00;
font-weight: bold;
}
#grid {
color: orange;
font-weight: bold;
}
#band {
color: #009900;
font-weight: bold;
}
#mode {
color: #ee0000;
font-weight: bold;
}
.rosterOn {
color: #ffffff;
}
.rosterOff {
color: #777777;
}
.imgGray {
-webkit-filter: grayscale(1); /* Google Chrome, Safari 6+ & Opera 15+ */
}
.imgNoFilter {
}
input:focus,
textarea:focus,
select:focus {
outline: none;
}
table {
border-collapse: collapse;
}
tr:hover td {
box-shadow: inset 0px 11px 6px -8px #888, inset 0px -11px 6px -8px #888;
}

Wyświetl plik

@ -50,6 +50,7 @@ var def_appSettings = {
gtSpotEnable: true,
heatEnabled: 0,
loadAdifAtStartup: false,
locale: "en",
lookupLoginCq: "",
lookupLoginQrz: "",
lookupLoginQth: "",

Wyświetl plik

@ -133,7 +133,6 @@ function loadAllSettings()
def_adifLogSettings
);
g_msgSettings = loadDefaultsAndMerge("msgSettings", def_msgSettings);
g_receptionSettings = loadDefaultsAndMerge(
"receptionSettings",
def_receptionSettings
@ -295,7 +294,7 @@ function saveAndCloseApp()
}
catch (e)
{
console.log(e);
console.error(e);
}
if (g_map)
@ -317,7 +316,7 @@ function saveAndCloseApp()
}
catch (e)
{
console.log(e);
console.error(e);
}
}
@ -346,7 +345,10 @@ function saveAndCloseApp()
g_baWindowHandle.window.close(true);
g_callRosterWindowHandle.window.close(true);
}
catch (e) { }
catch (e)
{
console.error(e);
}
nw.App.quit();
}
@ -2099,7 +2101,7 @@ function createSpotTipTable(toolElement)
}
catch (err)
{
console.log("Unexpected error at createSpotTipTable", toolElement, err)
console.error("Unexpected error at createSpotTipTable", toolElement, err)
}
}
@ -2435,7 +2437,10 @@ function renderTooltipWindow(feature)
g_popupWindowHandle.width = parseInt(positionInfo.width) + 20;
g_popupWindowHandle.height = parseInt(positionInfo.height) + 50;
}
catch (e) { }
catch (e)
{
console.error(e);
}
}
}
@ -2523,7 +2528,10 @@ function openConditionsWindow()
g_conditionsWindowHandle.hide();
}
}
catch (e) { }
catch (e)
{
console.error(e);
}
}
}
@ -2608,6 +2616,15 @@ function openCallRosterWindow(show = true)
});
}
);
try
{
// g_callRosterWindowHandle.window.loadRosteri18n();
}
catch (e)
{
console.error(e);
}
lockNewWindows();
}
else
@ -2631,8 +2648,12 @@ function openCallRosterWindow(show = true)
g_callRosterWindowHandle.hide();
}
}
// g_callRosterWindowHandle.window.loadRosteri18n();
}
catch (e)
{
console.error(e);
}
catch (e) { }
}
}
@ -2644,7 +2665,10 @@ function updateRosterWorked()
{
g_callRosterWindowHandle.window.updateWorked();
}
catch (e) { }
catch (e)
{
console.error(e);
}
}
}
@ -2656,7 +2680,10 @@ function updateRosterInstances()
{
g_callRosterWindowHandle.window.updateInstances();
}
catch (e) { }
catch (e)
{
console.error(e);
}
}
}
@ -2713,7 +2740,10 @@ function openStatsWindow(show = true)
g_statsWindowHandle.hide();
}
}
catch (e) { }
catch (e)
{
console.error(e);
}
}
}
@ -2758,7 +2788,10 @@ function showMessaging(show = true, cid)
g_chatWindowHandle.focus();
if (typeof cid != "undefined") g_chatWindowHandle.window.openId(cid);
}
catch (e) { }
catch (e)
{
console.error(e);
}
}
}
@ -2812,7 +2845,10 @@ function onRightClickGridSquare(feature)
{
renderTooltipWindow(feature);
}
catch (e) { }
catch (e)
{
console.error(e);
}
}
mouseOutOfDataItem();
}
@ -4037,7 +4073,10 @@ function reloadInfo(bandOrMode)
{
g_statsWindowHandle.window.reloadInfo();
}
catch (e) { }
catch (e)
{
console.error(e);
}
}
}
@ -6402,7 +6441,10 @@ function handleWsjtxStatus(newMessage)
{
g_callRosterWindowHandle.window.processStatus(newMessage);
}
catch (e) { }
catch (e)
{
console.error(e);
}
}
if (g_activeInstance == "")
@ -6798,7 +6840,7 @@ function handleWsjtxStatus(newMessage)
}
catch (err)
{
console.log("Unexpected error inside handleWsjtxStatus", err)
console.error("Unexpected error inside handleWsjtxStatus", err)
}
}
}
@ -7318,7 +7360,7 @@ function handleWsjtxDecode(newMessage)
}
catch (err)
{
console.log("Unexpected error inside handleWsjtxDecode 1", err)
console.error("Unexpected error inside handleWsjtxDecode 1", err)
}
}
}
@ -7362,7 +7404,7 @@ function handleWsjtxDecode(newMessage)
}
catch (err)
{
console.log("Unexpected error inside handleWsjtxDecode 2", err)
console.error("Unexpected error inside handleWsjtxDecode 2", err)
}
var feature = shapeFeature(
@ -7458,7 +7500,7 @@ function handleWsjtxDecode(newMessage)
}
catch (err)
{
console.log("Unexpected error inside handleWsjtxDecode 3", err)
console.error("Unexpected error inside handleWsjtxDecode 3", err)
}
}
}
@ -8589,7 +8631,7 @@ function showWorkedBox(sortIndex, nextPage, redraw)
}
catch (e)
{
console.log(e);
console.error(e);
}
}
@ -8624,6 +8666,7 @@ function lookupValidateCallByElement(elementString)
g_lookupWindowHandle.window.validateCallByElement(elementString);
}
}
function lookupFocus(selection)
{
if (
@ -9123,7 +9166,10 @@ function openBaWindow(show = true)
g_baWindowHandle.hide();
}
}
catch (e) { }
catch (e)
{
console.error(e);
}
}
}
@ -9175,7 +9221,10 @@ function openLookupWindow(show = false)
g_lookupWindowHandle.window.saveScreenSettings();
}
}
catch (e) { }
catch (e)
{
console.error(e);
}
}
}
@ -10813,7 +10862,10 @@ function setGtShareButtons()
{
g_chatWindowHandle.hide();
}
catch (e) { }
catch (e)
{
console.error(e);
}
}
}
@ -12434,6 +12486,7 @@ function readAcksFromDisk()
catch (e)
{
// file failed to load, probably not downloaded
console.error(e);
}
}
@ -13090,6 +13143,7 @@ function loadViewSettings()
gtModeFilter.value = g_appSettings.gtModeFilter;
gtPropFilter.value = g_appSettings.gtPropFilter;
distanceUnit.value = g_appSettings.distanceUnit;
languageLocale.value = g_appSettings.locale;
N1MMIpInput.value = g_N1MMSettings.ip;
N1MMPortInput.value = g_N1MMSettings.port;
buttonN1MMCheckBox.checked = g_N1MMSettings.enable;
@ -13381,7 +13435,10 @@ function startupButtonsAndInputs()
setGtShareButtons();
}
catch (e) { }
catch (e)
{
console.error(e);
}
}
function startupEventsAndTimers()
@ -13444,6 +13501,7 @@ document.addEventListener("drop", function (event)
var g_startupTable = [
[startupVersionInit, "Completed Version Check"],
[loadi18n, "Loading Locales"],
[qsoBackupFileInit, "QSO Backup Initialized"],
[callsignServicesInit, "Callsign Services Initialized"],
[loadMapSettings, "Map Settings Initialized"],
@ -13463,6 +13521,7 @@ var g_startupTable = [
[initSoundCards, "Sounds Initialized"],
[loadPortSettings, "Loaded Network Settings"],
[loadLookupDetails, "Callsign Lookup Details Loaded"],
[renderLocale, "Rendering Locale"],
[startupEventsAndTimers, "Set Events and Timers"],
[registerHotKeys, "Registered Hotkeys"],
[gtChatSystemInit, "Chat System Initialized"],
@ -13733,7 +13792,10 @@ function updateWsjtxListener(port)
{
g_wsjtUdpServer.dropMembership(g_appSettings.wsjtIP);
}
catch (e) { }
catch (e)
{
console.error(e);
}
}
g_wsjtUdpServer.close();
g_wsjtUdpServer = null;
@ -15456,6 +15518,7 @@ function is_dir(path)
catch (e)
{
// lstatSync throws an error if path doesn't exist
console.error(e);
return false;
}
}
@ -15485,7 +15548,7 @@ function purgeUserFiles(userDir, systemDir)
}
catch (e)
{
console.log(e);
console.error(e);
}
}
}
@ -15699,7 +15762,10 @@ function saveReceptionReports()
JSON.stringify(g_receptionReports)
);
}
catch (e) { }
catch (e)
{
console.error(e);
}
}
function loadReceptionReports()
@ -16002,7 +16068,7 @@ function createSpot(report, key, fromPoint, addToLayer = true)
}
catch (err)
{
console.log("Unexpected error inside createSpot", report, err)
console.error("Unexpected error inside createSpot", report, err)
}
}
@ -16290,7 +16356,10 @@ function setRosterTop()
{
g_callRosterWindowHandle.setAlwaysOnTop(g_appSettings.rosterAlwaysOnTop);
}
catch (e) { }
catch (e)
{
console.error(e);
}
}
}

Wyświetl plik

@ -0,0 +1,47 @@
function loadi18n()
{
$.i18n().load(
{
en: "i18n/en.json",
es: "i18n/es.json",
cn: "i18n/cn.json",
de: "i18n/de.json",
ja: "i18n/ja.json"
}).done(function ()
{
$.i18n().locale = g_appSettings.locale;
});
}
function renderI18n(locale)
{
$.i18n().locale = locale;
$("body").i18n();
}
function changeLocale()
{
g_appSettings.locale = languageLocale.value;
renderI18n(g_appSettings.locale);
}
function loadRosteri18n()
{
$.i18n().load(
{
en: "i18n/en.json",
es: "i18n/es.json",
cn: "i18n/cn.json",
de: "i18n/de.json",
js: "i18n/ja.json"
}).done(function ()
{
renderI18n(window.opener.g_appSettings.locale);
addControls();
});
}
function renderLocale()
{
renderI18n(g_appSettings.locale);
}

File diff suppressed because one or more lines are too long

Wyświetl plik

@ -0,0 +1,186 @@
/* eslint-disable no-tabs */
/*!
* jQuery Internationalization library
*
* Copyright (C) 2011-2013 Santhosh Thottingal, Neil Kandalgaonkar
*
* jquery.i18n is dual licensed GPLv2 or later and MIT. You don't have to do
* anything special to choose one license or the other and you don't have to
* notify anyone which license you are using. You are free to use
* UniversalLanguageSelector in commercial projects as long as the copyright
* header is left intact. See files GPL-LICENSE and MIT-LICENSE for details.
*
* @licence GNU General Public Licence 2.0 or later
* @licence MIT License
*/
(function ($)
{
"use strict";
var MessageParserEmitter = function ()
{
this.language = $.i18n.languages[String.locale] || $.i18n.languages.default;
};
MessageParserEmitter.prototype = {
constructor: MessageParserEmitter,
/**
* (We put this method definition here, and not in prototype, to make
* sure it's not overwritten by any magic.) Walk entire node structure,
* applying replacements and template functions when appropriate
*
* @param {Mixed} node abstract syntax tree (top node or subnode)
* @param {Array} replacements for $1, $2, ... $n
* @return {Mixed} single-string node or array of nodes suitable for
* jQuery appending.
*/
emit: function (node, replacements)
{
var ret, subnodes, operation,
messageParserEmitter = this;
switch (typeof node)
{
case "string":
case "number":
ret = node;
break;
case "object":
// node is an array of nodes
subnodes = $.map(node.slice(1), function (n)
{
return messageParserEmitter.emit(n, replacements);
});
operation = node[0].toLowerCase();
if (typeof messageParserEmitter[operation] === "function")
{
ret = messageParserEmitter[operation](subnodes, replacements);
}
else
{
throw new Error("unknown operation \"" + operation + "\"");
}
break;
case "undefined":
// Parsing the empty string (as an entire expression, or as a
// paramExpression in a template) results in undefined
// Perhaps a more clever parser can detect this, and return the
// empty string? Or is that useful information?
// The logical thing is probably to return the empty string here
// when we encounter undefined.
ret = "";
break;
default:
throw new Error("unexpected type in AST: " + typeof node);
}
return ret;
},
/**
* Parsing has been applied depth-first we can assume that all nodes
* here are single nodes Must return a single node to parents -- a
* jQuery with synthetic span However, unwrap any other synthetic spans
* in our children and pass them upwards
*
* @param {Array} nodes Mixed, some single nodes, some arrays of nodes.
* @return {string}
*/
concat: function (nodes)
{
var result = "";
$.each(nodes, function (i, node)
{
// strings, integers, anything else
result += node;
});
return result;
},
/**
* Return escaped replacement of correct index, or string if
* unavailable. Note that we expect the parsed parameter to be
* zero-based. i.e. $1 should have become [ 0 ]. if the specified
* parameter is not found return the same string (e.g. "$99" ->
* parameter 98 -> not found -> return "$99" ) TODO throw error if
* nodes.length > 1 ?
*
* @param {Array} nodes One element, integer, n >= 0
* @param {Array} replacements for $1, $2, ... $n
* @return {string} replacement
*/
replace: function (nodes, replacements)
{
var index = parseInt(nodes[0], 10);
if (index < replacements.length)
{
// replacement is not a string, don't touch!
return replacements[index];
}
else
{
// index not found, fallback to displaying variable
return "$" + (index + 1);
}
},
/**
* Transform parsed structure into pluralization n.b. The first node may
* be a non-integer (for instance, a string representing an Arabic
* number). So convert it back with the current language's
* convertNumber.
*
* @param {Array} nodes List [ {String|Number}, {String}, {String} ... ]
* @return {string} selected pluralized form according to current
* language.
*/
plural: function (nodes)
{
var count = parseFloat(this.language.convertNumber(nodes[0], 10)),
forms = nodes.slice(1);
return forms.length ? this.language.convertPlural(count, forms) : "";
},
/**
* Transform parsed structure into gender Usage
* {{gender:gender|masculine|feminine|neutral}}.
*
* @param {Array} nodes List [ {String}, {String}, {String} , {String} ]
* @return {string} selected gender form according to current language
*/
gender: function (nodes)
{
var gender = nodes[0],
forms = nodes.slice(1);
return this.language.gender(gender, forms);
},
/**
* Transform parsed structure into grammar conversion. Invoked by
* putting {{grammar:form|word}} in a message
*
* @param {Array} nodes List [{Grammar case eg: genitive}, {String word}]
* @return {string} selected grammatical form according to current
* language.
*/
grammar: function (nodes)
{
var form = nodes[0],
word = nodes[1];
return word && form && this.language.convertGrammar(word, form);
}
};
$.extend($.i18n.parser.emitter, new MessageParserEmitter());
}(jQuery));

Wyświetl plik

@ -0,0 +1,187 @@
/*!
* jQuery Internationalization library
*
* Copyright (C) 2012 Santhosh Thottingal
*
* jquery.i18n is dual licensed GPLv2 or later and MIT. You don't have to do anything special to
* choose one license or the other and you don't have to notify anyone which license you are using.
* You are free to use UniversalLanguageSelector in commercial projects as long as the copyright
* header is left intact. See files GPL-LICENSE and MIT-LICENSE for details.
*
* @licence GNU General Public Licence 2.0 or later
* @licence MIT License
*/
(function ($)
{
"use strict";
$.i18n = $.i18n || {};
$.extend($.i18n.fallbacks, {
ab: ["ru"],
ace: ["id"],
aln: ["sq"],
// Not so standard - als is supposed to be Tosk Albanian,
// but in Wikipedia it's used for a Germanic language.
als: ["gsw", "de"],
an: ["es"],
anp: ["hi"],
arn: ["es"],
arz: ["ar"],
av: ["ru"],
ay: ["es"],
ba: ["ru"],
bar: ["de"],
"bat-smg": ["sgs", "lt"],
bcc: ["fa"],
"be-x-old": ["be-tarask"],
bh: ["bho"],
bjn: ["id"],
bm: ["fr"],
bpy: ["bn"],
bqi: ["fa"],
bug: ["id"],
"cbk-zam": ["es"],
ce: ["ru"],
crh: ["crh-latn"],
"crh-cyrl": ["ru"],
csb: ["pl"],
cv: ["ru"],
"de-at": ["de"],
"de-ch": ["de"],
"de-formal": ["de"],
dsb: ["de"],
dtp: ["ms"],
egl: ["it"],
eml: ["it"],
ff: ["fr"],
fit: ["fi"],
"fiu-vro": ["vro", "et"],
frc: ["fr"],
frp: ["fr"],
frr: ["de"],
fur: ["it"],
gag: ["tr"],
gan: ["gan-hant", "zh-hant", "zh-hans"],
"gan-hans": ["zh-hans"],
"gan-hant": ["zh-hant", "zh-hans"],
gl: ["pt"],
glk: ["fa"],
gn: ["es"],
gsw: ["de"],
hif: ["hif-latn"],
hsb: ["de"],
ht: ["fr"],
ii: ["zh-cn", "zh-hans"],
inh: ["ru"],
iu: ["ike-cans"],
jut: ["da"],
jv: ["id"],
kaa: ["kk-latn", "kk-cyrl"],
kbd: ["kbd-cyrl"],
khw: ["ur"],
kiu: ["tr"],
kk: ["kk-cyrl"],
"kk-arab": ["kk-cyrl"],
"kk-latn": ["kk-cyrl"],
"kk-cn": ["kk-arab", "kk-cyrl"],
"kk-kz": ["kk-cyrl"],
"kk-tr": ["kk-latn", "kk-cyrl"],
kl: ["da"],
"ko-kp": ["ko"],
koi: ["ru"],
krc: ["ru"],
ks: ["ks-arab"],
ksh: ["de"],
ku: ["ku-latn"],
"ku-arab": ["ckb"],
kv: ["ru"],
lad: ["es"],
lb: ["de"],
lbe: ["ru"],
lez: ["ru"],
li: ["nl"],
lij: ["it"],
liv: ["et"],
lmo: ["it"],
ln: ["fr"],
ltg: ["lv"],
lzz: ["tr"],
mai: ["hi"],
"map-bms": ["jv", "id"],
mg: ["fr"],
mhr: ["ru"],
min: ["id"],
mo: ["ro"],
mrj: ["ru"],
mwl: ["pt"],
myv: ["ru"],
mzn: ["fa"],
nah: ["es"],
nap: ["it"],
nds: ["de"],
"nds-nl": ["nl"],
"nl-informal": ["nl"],
no: ["nb"],
os: ["ru"],
pcd: ["fr"],
pdc: ["de"],
pdt: ["de"],
pfl: ["de"],
pms: ["it"],
pt: ["pt-br"],
"pt-br": ["pt"],
qu: ["es"],
qug: ["qu", "es"],
rgn: ["it"],
rmy: ["ro"],
"roa-rup": ["rup"],
rue: ["uk", "ru"],
ruq: ["ruq-latn", "ro"],
"ruq-cyrl": ["mk"],
"ruq-latn": ["ro"],
sa: ["hi"],
sah: ["ru"],
scn: ["it"],
sg: ["fr"],
sgs: ["lt"],
sli: ["de"],
sr: ["sr-ec"],
srn: ["nl"],
stq: ["de"],
su: ["id"],
szl: ["pl"],
tcy: ["kn"],
tg: ["tg-cyrl"],
tt: ["tt-cyrl", "ru"],
"tt-cyrl": ["ru"],
ty: ["fr"],
udm: ["ru"],
ug: ["ug-arab"],
uk: ["ru"],
vec: ["it"],
vep: ["et"],
vls: ["nl"],
vmf: ["de"],
vot: ["fi"],
vro: ["et"],
wa: ["fr"],
wo: ["fr"],
wuu: ["zh-hans"],
xal: ["ru"],
xmf: ["ka"],
yi: ["he"],
za: ["zh-hans"],
zea: ["nl"],
zh: ["zh-hans"],
"zh-classical": ["lzh"],
"zh-cn": ["zh-hans"],
"zh-hant": ["zh-hans"],
"zh-hk": ["zh-hant", "zh-hans"],
"zh-min-nan": ["nan"],
"zh-mo": ["zh-hk", "zh-hant", "zh-hans"],
"zh-my": ["zh-sg", "zh-hans"],
"zh-sg": ["zh-hans"],
"zh-tw": ["zh-hant", "zh-hans"],
"zh-yue": ["yue"]
});
}(jQuery));

Wyświetl plik

@ -0,0 +1,333 @@
/* eslint-disable no-tabs */
/*!
* jQuery Internationalization library
*
* Copyright (C) 2012 Santhosh Thottingal
*
* jquery.i18n is dual licensed GPLv2 or later and MIT. You don't have to do
* anything special to choose one license or the other and you don't have to
* notify anyone which license you are using. You are free to use
* UniversalLanguageSelector in commercial projects as long as the copyright
* header is left intact. See files GPL-LICENSE and MIT-LICENSE for details.
*
* @licence GNU General Public Licence 2.0 or later
* @licence MIT License
*/
(function ($)
{
"use strict";
var I18N,
slice = Array.prototype.slice;
/**
* @constructor
* @param {Object} options
*/
I18N = function (options)
{
// Load defaults
this.options = $.extend({}, I18N.defaults, options);
this.parser = this.options.parser;
this.locale = this.options.locale;
this.messageStore = this.options.messageStore;
this.languages = {};
};
I18N.prototype = {
/**
* Localize a given messageKey to a locale.
* @param {string} messageKey
* @return {string} Localized message
*/
localize: function (messageKey)
{
var localeParts, localePartIndex, locale, fallbackIndex,
tryingLocale, message;
locale = this.locale;
fallbackIndex = 0;
while (locale)
{
// Iterate through locales starting at most-specific until
// localization is found. As in fi-Latn-FI, fi-Latn and fi.
localeParts = locale.split("-");
localePartIndex = localeParts.length;
do
{
tryingLocale = localeParts.slice(0, localePartIndex).join("-");
message = this.messageStore.get(tryingLocale, messageKey);
if (message)
{
return message;
}
localePartIndex--;
} while (localePartIndex);
if (locale === this.options.fallbackLocale)
{
break;
}
locale = ($.i18n.fallbacks[this.locale] &&
$.i18n.fallbacks[this.locale][fallbackIndex]) ||
this.options.fallbackLocale;
$.i18n.log("Trying fallback locale for " + this.locale + ": " + locale + " (" + messageKey + ")");
fallbackIndex++;
}
// key not found
return "";
},
/*
* Destroy the i18n instance.
*/
destroy: function ()
{
$.removeData(document, "i18n");
},
/**
* General message loading API This can take a URL string for
* the json formatted messages. Example:
* <code>load('path/to/all_localizations.json');</code>
*
* To load a localization file for a locale:
* <code>
* load('path/to/de-messages.json', 'de' );
* </code>
*
* To load a localization file from a directory:
* <code>
* load('path/to/i18n/directory', 'de' );
* </code>
* The above method has the advantage of fallback resolution.
* ie, it will automatically load the fallback locales for de.
* For most usecases, this is the recommended method.
* It is optional to have trailing slash at end.
*
* A data object containing message key- message translation mappings
* can also be passed. Example:
* <code>
* load( { 'hello' : 'Hello' }, optionalLocale );
* </code>
*
* A source map containing key-value pair of languagename and locations
* can also be passed. Example:
* <code>
* load( {
* bn: 'i18n/bn.json',
* he: 'i18n/he.json',
* en: 'i18n/en.json'
* } )
* </code>
*
* If the data argument is null/undefined/false,
* all cached messages for the i18n instance will get reset.
*
* @param {string|Object} source
* @param {string} locale Language tag
* @return {jQuery.Promise}
*/
load: function (source, locale)
{
var fallbackLocales, locIndex, fallbackLocale, sourceMap = {};
if (!source && !locale)
{
source = "i18n/" + $.i18n().locale + ".json";
locale = $.i18n().locale;
}
if (typeof source === "string" &&
// source extension should be json, but can have query params after that.
source.split("?")[0].split(".").pop() !== "json"
)
{
// Load specified locale then check for fallbacks when directory is
// specified in load()
sourceMap[locale] = source + "/" + locale + ".json";
fallbackLocales = ($.i18n.fallbacks[locale] || [])
.concat(this.options.fallbackLocale);
for (locIndex = 0; locIndex < fallbackLocales.length; locIndex++)
{
fallbackLocale = fallbackLocales[locIndex];
sourceMap[fallbackLocale] = source + "/" + fallbackLocale + ".json";
}
return this.load(sourceMap);
}
else
{
return this.messageStore.load(source, locale);
}
},
/**
* Does parameter and magic word substitution.
*
* @param {string} key Message key
* @param {Array} parameters Message parameters
* @return {string}
*/
parse: function (key, parameters)
{
var message = this.localize(key);
// FIXME: This changes the state of the I18N object,
// should probably not change the 'this.parser' but just
// pass it to the parser.
this.parser.language = $.i18n.languages[$.i18n().locale] || $.i18n.languages.default;
if (message === "")
{
message = key;
}
return this.parser.parse(message, parameters);
}
};
/**
* Process a message from the $.I18N instance
* for the current document, stored in jQuery.data(document).
*
* @param {string} key Key of the message.
* @param {string} param1 [param...] Variadic list of parameters for {key}.
* @return {string|$.I18N} Parsed message, or if no key was given
* the instance of $.I18N is returned.
*/
$.i18n = function (key, param1)
{
var parameters,
i18n = $.data(document, "i18n"),
options = typeof key === "object" && key;
// If the locale option for this call is different then the setup so far,
// update it automatically. This doesn't just change the context for this
// call but for all future call as well.
// If there is no i18n setup yet, don't do this. It will be taken care of
// by the `new I18N` construction below.
// NOTE: It should only change language for this one call.
// Then cache instances of I18N somewhere.
if (options && options.locale && i18n && i18n.locale !== options.locale)
{
i18n.locale = options.locale;
}
if (!i18n)
{
i18n = new I18N(options);
$.data(document, "i18n", i18n);
}
if (typeof key === "string")
{
if (param1 !== undefined)
{
parameters = slice.call(arguments, 1);
}
else
{
parameters = [];
}
return i18n.parse(key, parameters);
}
else
{
// FIXME: remove this feature/bug.
return i18n;
}
};
$.fn.i18n = function ()
{
var i18n = $.data(document, "i18n");
if (!i18n)
{
i18n = new I18N();
$.data(document, "i18n", i18n);
}
return this.each(function ()
{
var $this = $(this),
messageKey = $this.data("i18n"),
lBracket, rBracket, type, key;
if (messageKey)
{
lBracket = messageKey.indexOf("[");
rBracket = messageKey.indexOf("]");
if (lBracket !== -1 && rBracket !== -1 && lBracket < rBracket)
{
type = messageKey.slice(lBracket + 1, rBracket);
key = messageKey.slice(rBracket + 1);
if (type === "html")
{
$this.html(i18n.parse(key));
}
else
{
$this.attr(type, i18n.parse(key));
}
}
else
{
$this.text(i18n.parse(messageKey));
}
}
else
{
$this.find("[data-i18n]").i18n();
}
});
};
function getDefaultLocale()
{
var locale = $("html").attr("lang");
if (!locale)
{
locale = navigator.language || navigator.userLanguage || "";
}
return locale;
}
$.i18n.languages = {};
$.i18n.messageStore = $.i18n.messageStore || {};
$.i18n.parser = {
// The default parser only handles variable substitution
parse: function (message, parameters)
{
return message.replace(/\$(\d+)/g, function (str, match)
{
var index = parseInt(match, 10) - 1;
return parameters[index] !== undefined ? parameters[index] : "$" + match;
});
},
emitter: {}
};
$.i18n.fallbacks = {};
$.i18n.debug = false;
$.i18n.log = function (/* arguments */)
{
if (window.console && $.i18n.debug)
{
window.console.log.apply(window.console, arguments);
}
};
/* Static members */
I18N.defaults = {
locale: getDefaultLocale(),
fallbackLocale: "en",
parser: $.i18n.parser,
messageStore: $.i18n.messageStore
};
// Expose constructor
$.i18n.constructor = I18N;
}(jQuery));

Wyświetl plik

@ -0,0 +1,530 @@
/* eslint-disable no-tabs */
/* global pluralRuleParser */
(function ($)
{
"use strict";
// jscs:disable
var language = {
// CLDR plural rules generated using
// libs/CLDRPluralRuleParser/tools/PluralXML2JSON.html
pluralRules: {
ak: {
one: "n = 0..1"
},
am: {
one: "i = 0 or n = 1"
},
ar: {
zero: "n = 0",
one: "n = 1",
two: "n = 2",
few: "n % 100 = 3..10",
many: "n % 100 = 11..99"
},
ars: {
zero: "n = 0",
one: "n = 1",
two: "n = 2",
few: "n % 100 = 3..10",
many: "n % 100 = 11..99"
},
as: {
one: "i = 0 or n = 1"
},
be: {
one: "n % 10 = 1 and n % 100 != 11",
few: "n % 10 = 2..4 and n % 100 != 12..14",
many: "n % 10 = 0 or n % 10 = 5..9 or n % 100 = 11..14"
},
bh: {
one: "n = 0..1"
},
bn: {
one: "i = 0 or n = 1"
},
br: {
one: "n % 10 = 1 and n % 100 != 11,71,91",
two: "n % 10 = 2 and n % 100 != 12,72,92",
few: "n % 10 = 3..4,9 and n % 100 != 10..19,70..79,90..99",
many: "n != 0 and n % 1000000 = 0"
},
bs: {
one: "v = 0 and i % 10 = 1 and i % 100 != 11 or f % 10 = 1 and f % 100 != 11",
few: "v = 0 and i % 10 = 2..4 and i % 100 != 12..14 or f % 10 = 2..4 and f % 100 != 12..14"
},
cs: {
one: "i = 1 and v = 0",
few: "i = 2..4 and v = 0",
many: "v != 0"
},
cy: {
zero: "n = 0",
one: "n = 1",
two: "n = 2",
few: "n = 3",
many: "n = 6"
},
da: {
one: "n = 1 or t != 0 and i = 0,1"
},
dsb: {
one: "v = 0 and i % 100 = 1 or f % 100 = 1",
two: "v = 0 and i % 100 = 2 or f % 100 = 2",
few: "v = 0 and i % 100 = 3..4 or f % 100 = 3..4"
},
fa: {
one: "i = 0 or n = 1"
},
ff: {
one: "i = 0,1"
},
fil: {
one: "v = 0 and i = 1,2,3 or v = 0 and i % 10 != 4,6,9 or v != 0 and f % 10 != 4,6,9"
},
fr: {
one: "i = 0,1"
},
ga: {
one: "n = 1",
two: "n = 2",
few: "n = 3..6",
many: "n = 7..10"
},
gd: {
one: "n = 1,11",
two: "n = 2,12",
few: "n = 3..10,13..19"
},
gu: {
one: "i = 0 or n = 1"
},
guw: {
one: "n = 0..1"
},
gv: {
one: "v = 0 and i % 10 = 1",
two: "v = 0 and i % 10 = 2",
few: "v = 0 and i % 100 = 0,20,40,60,80",
many: "v != 0"
},
he: {
one: "i = 1 and v = 0",
two: "i = 2 and v = 0",
many: "v = 0 and n != 0..10 and n % 10 = 0"
},
hi: {
one: "i = 0 or n = 1"
},
hr: {
one: "v = 0 and i % 10 = 1 and i % 100 != 11 or f % 10 = 1 and f % 100 != 11",
few: "v = 0 and i % 10 = 2..4 and i % 100 != 12..14 or f % 10 = 2..4 and f % 100 != 12..14"
},
hsb: {
one: "v = 0 and i % 100 = 1 or f % 100 = 1",
two: "v = 0 and i % 100 = 2 or f % 100 = 2",
few: "v = 0 and i % 100 = 3..4 or f % 100 = 3..4"
},
hy: {
one: "i = 0,1"
},
is: {
one: "t = 0 and i % 10 = 1 and i % 100 != 11 or t != 0"
},
iu: {
one: "n = 1",
two: "n = 2"
},
iw: {
one: "i = 1 and v = 0",
two: "i = 2 and v = 0",
many: "v = 0 and n != 0..10 and n % 10 = 0"
},
kab: {
one: "i = 0,1"
},
kn: {
one: "i = 0 or n = 1"
},
kw: {
one: "n = 1",
two: "n = 2"
},
lag: {
zero: "n = 0",
one: "i = 0,1 and n != 0"
},
ln: {
one: "n = 0..1"
},
lt: {
one: "n % 10 = 1 and n % 100 != 11..19",
few: "n % 10 = 2..9 and n % 100 != 11..19",
many: "f != 0"
},
lv: {
zero: "n % 10 = 0 or n % 100 = 11..19 or v = 2 and f % 100 = 11..19",
one: "n % 10 = 1 and n % 100 != 11 or v = 2 and f % 10 = 1 and f % 100 != 11 or v != 2 and f % 10 = 1"
},
mg: {
one: "n = 0..1"
},
mk: {
one: "v = 0 and i % 10 = 1 or f % 10 = 1"
},
mo: {
one: "i = 1 and v = 0",
few: "v != 0 or n = 0 or n != 1 and n % 100 = 1..19"
},
mr: {
one: "i = 0 or n = 1"
},
mt: {
one: "n = 1",
few: "n = 0 or n % 100 = 2..10",
many: "n % 100 = 11..19"
},
naq: {
one: "n = 1",
two: "n = 2"
},
nso: {
one: "n = 0..1"
},
pa: {
one: "n = 0..1"
},
pl: {
one: "i = 1 and v = 0",
few: "v = 0 and i % 10 = 2..4 and i % 100 != 12..14",
many: "v = 0 and i != 1 and i % 10 = 0..1 or v = 0 and i % 10 = 5..9 or v = 0 and i % 100 = 12..14"
},
prg: {
zero: "n % 10 = 0 or n % 100 = 11..19 or v = 2 and f % 100 = 11..19",
one: "n % 10 = 1 and n % 100 != 11 or v = 2 and f % 10 = 1 and f % 100 != 11 or v != 2 and f % 10 = 1"
},
pt: {
one: "i = 0..1"
},
ro: {
one: "i = 1 and v = 0",
few: "v != 0 or n = 0 or n != 1 and n % 100 = 1..19"
},
ru: {
one: "v = 0 and i % 10 = 1 and i % 100 != 11",
few: "v = 0 and i % 10 = 2..4 and i % 100 != 12..14",
many: "v = 0 and i % 10 = 0 or v = 0 and i % 10 = 5..9 or v = 0 and i % 100 = 11..14"
},
se: {
one: "n = 1",
two: "n = 2"
},
sh: {
one: "v = 0 and i % 10 = 1 and i % 100 != 11 or f % 10 = 1 and f % 100 != 11",
few: "v = 0 and i % 10 = 2..4 and i % 100 != 12..14 or f % 10 = 2..4 and f % 100 != 12..14"
},
shi: {
one: "i = 0 or n = 1",
few: "n = 2..10"
},
si: {
one: "n = 0,1 or i = 0 and f = 1"
},
sk: {
one: "i = 1 and v = 0",
few: "i = 2..4 and v = 0",
many: "v != 0"
},
sl: {
one: "v = 0 and i % 100 = 1",
two: "v = 0 and i % 100 = 2",
few: "v = 0 and i % 100 = 3..4 or v != 0"
},
sma: {
one: "n = 1",
two: "n = 2"
},
smi: {
one: "n = 1",
two: "n = 2"
},
smj: {
one: "n = 1",
two: "n = 2"
},
smn: {
one: "n = 1",
two: "n = 2"
},
sms: {
one: "n = 1",
two: "n = 2"
},
sr: {
one: "v = 0 and i % 10 = 1 and i % 100 != 11 or f % 10 = 1 and f % 100 != 11",
few: "v = 0 and i % 10 = 2..4 and i % 100 != 12..14 or f % 10 = 2..4 and f % 100 != 12..14"
},
ti: {
one: "n = 0..1"
},
tl: {
one: "v = 0 and i = 1,2,3 or v = 0 and i % 10 != 4,6,9 or v != 0 and f % 10 != 4,6,9"
},
tzm: {
one: "n = 0..1 or n = 11..99"
},
uk: {
one: "v = 0 and i % 10 = 1 and i % 100 != 11",
few: "v = 0 and i % 10 = 2..4 and i % 100 != 12..14",
many: "v = 0 and i % 10 = 0 or v = 0 and i % 10 = 5..9 or v = 0 and i % 100 = 11..14"
},
wa: {
one: "n = 0..1"
},
zu: {
one: "i = 0 or n = 1"
}
},
// jscs:enable
/**
* Plural form transformations, needed for some languages.
*
* @param {integer} count
* Non-localized quantifier
* @param {Array} forms
* List of plural forms
* @return {string} Correct form for quantifier in this language
*/
convertPlural: function (count, forms)
{
var pluralRules,
pluralFormIndex,
index,
explicitPluralPattern = /\d+=/i,
formCount,
form;
if (!forms || forms.length === 0)
{
return "";
}
// Handle for Explicit 0= & 1= values
for (index = 0; index < forms.length; index++)
{
form = forms[index];
if (explicitPluralPattern.test(form))
{
formCount = parseInt(form.slice(0, form.indexOf("=")), 10);
if (formCount === count)
{
return (form.slice(form.indexOf("=") + 1));
}
forms[index] = undefined;
}
}
forms = $.map(forms, function (form)
{
if (form !== undefined)
{
return form;
}
});
pluralRules = this.pluralRules[$.i18n().locale];
if (!pluralRules)
{
// default fallback.
return (count === 1) ? forms[0] : forms[1];
}
pluralFormIndex = this.getPluralForm(count, pluralRules);
pluralFormIndex = Math.min(pluralFormIndex, forms.length - 1);
return forms[pluralFormIndex];
},
/**
* For the number, get the plural for index
*
* @param {integer} number
* @param {Object} pluralRules
* @return {integer} plural form index
*/
getPluralForm: function (number, pluralRules)
{
var i,
pluralForms = ["zero", "one", "two", "few", "many", "other"],
pluralFormIndex = 0;
for (i = 0; i < pluralForms.length; i++)
{
if (pluralRules[pluralForms[i]])
{
if (pluralRuleParser(pluralRules[pluralForms[i]], number))
{
return pluralFormIndex;
}
pluralFormIndex++;
}
}
return pluralFormIndex;
},
/**
* Converts a number using digitTransformTable.
*
* @param {number} num Value to be converted
* @param {boolean} integer Convert the return value to an integer
* @return {string} The number converted into a String.
*/
convertNumber: function (num, integer)
{
var tmp, item, i,
transformTable, numberString, convertedNumber;
// Set the target Transform table:
transformTable = this.digitTransformTable($.i18n().locale);
numberString = String(num);
convertedNumber = "";
if (!transformTable)
{
return num;
}
// Check if the restore to Latin number flag is set:
if (integer)
{
if (parseFloat(num, 10) === num)
{
return num;
}
tmp = [];
for (item in transformTable)
{
tmp[transformTable[item]] = item;
}
transformTable = tmp;
}
for (i = 0; i < numberString.length; i++)
{
if (transformTable[numberString[i]])
{
convertedNumber += transformTable[numberString[i]];
}
else
{
convertedNumber += numberString[i];
}
}
return integer ? parseFloat(convertedNumber, 10) : convertedNumber;
},
/**
* Grammatical transformations, needed for inflected languages.
* Invoked by putting {{grammar:form|word}} in a message.
* Override this method for languages that need special grammar rules
* applied dynamically.
*
* @param {string} word
* @param {string} form
* @return {string}
*/
// eslint-disable-next-line no-unused-vars
convertGrammar: function (word, form)
{
return word;
},
/**
* Provides an alternative text depending on specified gender. Usage
* {{gender:[gender|user object]|masculine|feminine|neutral}}. If second
* or third parameter are not specified, masculine is used.
*
* These details may be overriden per language.
*
* @param {string} gender
* male, female, or anything else for neutral.
* @param {Array} forms
* List of gender forms
*
* @return {string}
*/
gender: function (gender, forms)
{
if (!forms || forms.length === 0)
{
return "";
}
while (forms.length < 2)
{
forms.push(forms[forms.length - 1]);
}
if (gender === "male")
{
return forms[0];
}
if (gender === "female")
{
return forms[1];
}
return (forms.length === 3) ? forms[2] : forms[0];
},
/**
* Get the digit transform table for the given language
* See http://cldr.unicode.org/translation/numbering-systems
*
* @param {string} language
* @return {Array|boolean} List of digits in the passed language or false
* representation, or boolean false if there is no information.
*/
digitTransformTable: function (language)
{
var tables = {
ar: "٠١٢٣٤٥٦٧٨٩",
fa: "۰۱۲۳۴۵۶۷۸۹",
ml: "൦൧൨൩൪൫൬൭൮൯",
kn: "೦೧೨೩೪೫೬೭೮೯",
lo: "໐໑໒໓໔໕໖໗໘໙",
or: "୦୧୨୩୪୫୬୭୮୯",
kh: "០១២៣៤៥៦៧៨៩",
nqo: "߀߁߂߃߄߅߆߇߈߉", // Note that the digits go right to left
pa: "੦੧੨੩੪੫੬੭੮੯",
gu: "૦૧૨૩૪૫૬૭૮૯",
hi: "०१२३४५६७८९",
my: "၀၁၂၃၄၅၆၇၈၉",
ta: "௦௧௨௩௪௫௬௭௮௯",
te: "౦౧౨౩౪౫౬౭౮౯",
th: "๐๑๒๓๔๕๖๗๘๙", // FIXME use iso 639 codes
bo: "༠༡༢༣༤༥༦༧༨༩" // FIXME use iso 639 codes
};
if (!tables[language])
{
return false;
}
return tables[language].split("");
}
};
$.extend($.i18n.languages, {
default: language
});
}(jQuery));

Wyświetl plik

@ -0,0 +1,140 @@
/* eslint-disable no-tabs */
/*!
* jQuery Internationalization library - Message Store
*
* Copyright (C) 2012 Santhosh Thottingal
*
* jquery.i18n is dual licensed GPLv2 or later and MIT. You don't have to do anything special to
* choose one license or the other and you don't have to notify anyone which license you are using.
* You are free to use UniversalLanguageSelector in commercial projects as long as the copyright
* header is left intact. See files GPL-LICENSE and MIT-LICENSE for details.
*
* @licence GNU General Public Licence 2.0 or later
* @licence MIT License
*/
(function ($)
{
"use strict";
var MessageStore = function ()
{
this.messages = {};
this.sources = {};
};
function jsonMessageLoader(url)
{
var deferred = $.Deferred();
$.getJSON(url)
.done(deferred.resolve)
.fail(function (jqxhr, settings, exception)
{
$.i18n.log("Error in loading messages from " + url + " Exception: " + exception);
// Ignore 404 exception, because we are handling fallabacks explicitly
deferred.resolve();
});
return deferred.promise();
}
/**
* See https://github.com/wikimedia/jquery.i18n/wiki/Specification#wiki-Message_File_Loading
*/
MessageStore.prototype = {
/**
* General message loading API This can take a URL string for
* the json formatted messages.
* <code>load('path/to/all_localizations.json');</code>
*
* This can also load a localization file for a locale <code>
* load( 'path/to/de-messages.json', 'de' );
* </code>
* A data object containing message key- message translation mappings
* can also be passed Eg:
* <code>
* load( { 'hello' : 'Hello' }, optionalLocale );
* </code> If the data argument is
* null/undefined/false,
* all cached messages for the i18n instance will get reset.
*
* @param {string|Object} source
* @param {string} locale Language tag
* @return {jQuery.Promise}
*/
load: function (source, locale)
{
var key = null,
deferreds = [],
messageStore = this;
if (typeof source === "string")
{
// This is a URL to the messages file.
$.i18n.log("Loading messages from: " + source);
return jsonMessageLoader(source)
.then(function (localization)
{
return messageStore.load(localization, locale);
});
}
if (locale)
{
// source is an key-value pair of messages for given locale
messageStore.set(locale, source);
return $.Deferred().resolve();
}
else
{
// source is a key-value pair of locales and their source
for (key in source)
{
if (Object.prototype.hasOwnProperty.call(source, key))
{
locale = key;
// No {locale} given, assume data is a group of languages,
// call this function again for each language.
deferreds.push(messageStore.load(source[key], locale));
}
}
return $.when.apply($, deferreds);
}
},
/**
* Set messages to the given locale.
* If locale exists, add messages to the locale.
*
* @param {string} locale
* @param {Object} messages
*/
set: function (locale, messages)
{
if (!this.messages[locale])
{
this.messages[locale] = messages;
}
else
{
this.messages[locale] = $.extend(this.messages[locale], messages);
}
},
/**
*
* @param {string} locale
* @param {string} messageKey
* @return {boolean}
*/
get: function (locale, messageKey)
{
return this.messages[locale] && this.messages[locale][messageKey];
}
};
$.extend($.i18n.messageStore, new MessageStore());
}(jQuery));

Wyświetl plik

@ -0,0 +1,354 @@
/* eslint-disable no-tabs */
/*!
* jQuery Internationalization library
*
* Copyright (C) 2011-2013 Santhosh Thottingal, Neil Kandalgaonkar
*
* jquery.i18n is dual licensed GPLv2 or later and MIT. You don't have to do
* anything special to choose one license or the other and you don't have to
* notify anyone which license you are using. You are free to use
* UniversalLanguageSelector in commercial projects as long as the copyright
* header is left intact. See files GPL-LICENSE and MIT-LICENSE for details.
*
* @licence GNU General Public Licence 2.0 or later
* @licence MIT License
*/
(function ($)
{
"use strict";
var MessageParser = function (options)
{
this.options = $.extend({}, $.i18n.parser.defaults, options);
this.language = $.i18n.languages[String.locale] || $.i18n.languages.default;
this.emitter = $.i18n.parser.emitter;
};
MessageParser.prototype = {
constructor: MessageParser,
simpleParse: function (message, parameters)
{
return message.replace(/\$(\d+)/g, function (str, match)
{
var index = parseInt(match, 10) - 1;
return parameters[index] !== undefined ? parameters[index] : "$" + match;
});
},
parse: function (message, replacements)
{
if (message.indexOf("{{") < 0)
{
return this.simpleParse(message, replacements);
}
this.emitter.language = $.i18n.languages[$.i18n().locale] ||
$.i18n.languages.default;
return this.emitter.emit(this.ast(message), replacements);
},
ast: function (message)
{
var pipe, colon, backslash, anyCharacter, dollar, digits, regularLiteral,
regularLiteralWithoutBar, regularLiteralWithoutSpace, escapedOrLiteralWithoutBar,
escapedOrRegularLiteral, templateContents, templateName, openTemplate,
closeTemplate, expression, paramExpression, result,
pos = 0;
// Try parsers until one works, if none work return null
function choice(parserSyntax)
{
return function ()
{
var i, result;
for (i = 0; i < parserSyntax.length; i++)
{
result = parserSyntax[i]();
if (result !== null)
{
return result;
}
}
return null;
};
}
// Try several parserSyntax-es in a row.
// All must succeed; otherwise, return null.
// This is the only eager one.
function sequence(parserSyntax)
{
var i, res,
originalPos = pos,
result = [];
for (i = 0; i < parserSyntax.length; i++)
{
res = parserSyntax[i]();
if (res === null)
{
pos = originalPos;
return null;
}
result.push(res);
}
return result;
}
// Run the same parser over and over until it fails.
// Must succeed a minimum of n times; otherwise, return null.
function nOrMore(n, p)
{
return function ()
{
var originalPos = pos,
result = [],
parsed = p();
while (parsed !== null)
{
result.push(parsed);
parsed = p();
}
if (result.length < n)
{
pos = originalPos;
return null;
}
return result;
};
}
// Helpers -- just make parserSyntax out of simpler JS builtin types
function makeStringParser(s)
{
var len = s.length;
return function ()
{
var result = null;
if (message.slice(pos, pos + len) === s)
{
result = s;
pos += len;
}
return result;
};
}
function makeRegexParser(regex)
{
return function ()
{
var matches = message.slice(pos).match(regex);
if (matches === null)
{
return null;
}
pos += matches[0].length;
return matches[0];
};
}
pipe = makeStringParser("|");
colon = makeStringParser(":");
backslash = makeStringParser("\\");
anyCharacter = makeRegexParser(/^./);
dollar = makeStringParser("$");
digits = makeRegexParser(/^\d+/);
regularLiteral = makeRegexParser(/^[^{}[\]$\\]/);
regularLiteralWithoutBar = makeRegexParser(/^[^{}[\]$\\|]/);
regularLiteralWithoutSpace = makeRegexParser(/^[^{}[\]$\s]/);
// There is a general pattern:
// parse a thing;
// if it worked, apply transform,
// otherwise return null.
// But using this as a combinator seems to cause problems
// when combined with nOrMore().
// May be some scoping issue.
function transform(p, fn)
{
return function ()
{
var result = p();
return result === null ? null : fn(result);
};
}
// Used to define "literals" within template parameters. The pipe
// character is the parameter delimeter, so by default
// it is not a literal in the parameter
function literalWithoutBar()
{
var result = nOrMore(1, escapedOrLiteralWithoutBar)();
return result === null ? null : result.join("");
}
function literal()
{
var result = nOrMore(1, escapedOrRegularLiteral)();
return result === null ? null : result.join("");
}
function escapedLiteral()
{
var result = sequence([backslash, anyCharacter]);
return result === null ? null : result[1];
}
choice([escapedLiteral, regularLiteralWithoutSpace]);
escapedOrLiteralWithoutBar = choice([escapedLiteral, regularLiteralWithoutBar]);
escapedOrRegularLiteral = choice([escapedLiteral, regularLiteral]);
function replacement()
{
var result = sequence([dollar, digits]);
if (result === null)
{
return null;
}
return ["REPLACE", parseInt(result[1], 10) - 1];
}
templateName = transform(
// see $wgLegalTitleChars
// not allowing : due to the need to catch "PLURAL:$1"
makeRegexParser(/^[ !"$&'()*,./0-9;=?@A-Z^_`a-z~\x80-\xFF+-]+/),
function (result)
{
return result.toString();
}
);
function templateParam()
{
var expr,
result = sequence([pipe, nOrMore(0, paramExpression)]);
if (result === null)
{
return null;
}
expr = result[1];
// use a "CONCAT" operator if there are multiple nodes,
// otherwise return the first node, raw.
return expr.length > 1 ? ["CONCAT"].concat(expr) : expr[0];
}
function templateWithReplacement()
{
var result = sequence([templateName, colon, replacement]);
return result === null ? null : [result[0], result[2]];
}
function templateWithOutReplacement()
{
var result = sequence([templateName, colon, paramExpression]);
return result === null ? null : [result[0], result[2]];
}
templateContents = choice([
function ()
{
var res = sequence([
// templates can have placeholders for dynamic
// replacement eg: {{PLURAL:$1|one car|$1 cars}}
// or no placeholders eg:
// {{GRAMMAR:genitive|{{SITENAME}}}
choice([templateWithReplacement, templateWithOutReplacement]),
nOrMore(0, templateParam)
]);
return res === null ? null : res[0].concat(res[1]);
},
function ()
{
var res = sequence([templateName, nOrMore(0, templateParam)]);
if (res === null)
{
return null;
}
return [res[0]].concat(res[1]);
}
]);
openTemplate = makeStringParser("{{");
closeTemplate = makeStringParser("}}");
function template()
{
var result = sequence([openTemplate, templateContents, closeTemplate]);
return result === null ? null : result[1];
}
expression = choice([template, replacement, literal]);
paramExpression = choice([template, replacement, literalWithoutBar]);
function start()
{
var result = nOrMore(0, expression)();
if (result === null)
{
return null;
}
return ["CONCAT"].concat(result);
}
result = start();
/*
* For success, the pos must have gotten to the end of the input
* and returned a non-null.
* n.b. This is part of language infrastructure, so we do not throw an
* internationalizable message.
*/
if (result === null || pos !== message.length)
{
throw new Error("Parse error at position " + pos.toString() + " in input: " + message);
}
return result;
}
};
$.extend($.i18n.parser, new MessageParser());
}(jQuery));

Wyświetl plik

@ -1576,15 +1576,12 @@ function init()
g_callsignDatabaseDXCC = window.opener.g_callsignDatabaseDXCC;
g_callsignDatabaseUS = window.opener.g_callsignDatabaseUS;
g_callsignDatabaseUSplus = window.opener.g_callsignDatabaseUSplus;
loadAwardJson();
updateWorked();
// addAllAwards();
window.addEventListener("message", receiveMessage, false);
lockNewWindows();
if (window.opener.g_mapSettings.offlineMode == false)
@ -1597,9 +1594,14 @@ function init()
80
);
}
loadSettings();
loadRosteri18n();
g_timerInterval = setInterval(realtimeRoster, 1000);
updateInstances();
}
function addControls()
{
window.opener.setRosterSpot(g_rosterSettings.columns.Spot);
for (const key in g_rosterSettings.wanted)
@ -1687,7 +1689,8 @@ function init()
item = new nw.MenuItem({
type: "normal",
label: "Lookup",
// label: "Lookup",
label: $.i18n("roster.menu.Lookup"),
click: function ()
{
callLookup(g_targetHash, "");
@ -1698,7 +1701,8 @@ function init()
item = new nw.MenuItem({
type: "normal",
label: "Gen Msgs",
// label: "Gen Msgs",
label: $.i18n("roster.menu.GenMesg"),
click: function ()
{
callGenMessage(g_targetHash, "");
@ -2131,7 +2135,6 @@ function init()
document.addEventListener("keydown", onMyKeyDown, false);
initDXCCSelector();
g_timerInterval = nodeTimers.setInterval(realtimeRoster, 1000);
updateInstances();

Wyświetl plik

@ -18,6 +18,9 @@
"webkit": {
"plugin": true
},
"dependencies": {
"jquery": "^3.5.0"
},
"scripts": {
"test": "eslint .",
"start": "run --mirror https://dl.nwjs.io/ ."