From b5f7aa1813c9c82d6f6a05a506dc3b9012f3222b Mon Sep 17 00:00:00 2001 From: Chris Walsh Date: Wed, 1 Dec 2021 19:25:00 -0800 Subject: [PATCH 1/3] Add languages to metrics API endpoint --- hooks/useLanguageNames.js | 34 ++++++ pages/api/website/[id]/metrics.js | 16 ++- public/language/en-US.json | 184 ++++++++++++++++++++++++++++++ 3 files changed, 232 insertions(+), 2 deletions(-) create mode 100644 hooks/useLanguageNames.js create mode 100644 public/language/en-US.json diff --git a/hooks/useLanguageNames.js b/hooks/useLanguageNames.js new file mode 100644 index 00000000..ef179185 --- /dev/null +++ b/hooks/useLanguageNames.js @@ -0,0 +1,34 @@ +import { useState, useEffect } from 'react'; +import { useRouter } from 'next/router'; +import { get } from 'lib/web'; +import enUS from 'public/language/en-US.json'; + +const languageNames = { + 'en-US': enUS, +}; + +export default function useLanguageNames(locale) { + const [list, setList] = useState(languageNames[locale] || enUS); + const { basePath } = useRouter(); + + async function loadData(locale) { + const { ok, data } = await get(`${basePath}/language/${locale}.json`); + + if (ok) { + languageNames[locale] = data; + setList(languageNames[locale]); + } else { + setList(enUS); + } + } + + useEffect(() => { + if (!languageNames[locale]) { + loadData(locale); + } else { + setList(languageNames[locale]); + } + }, [locale]); + + return list; +} diff --git a/pages/api/website/[id]/metrics.js b/pages/api/website/[id]/metrics.js index 3e9b9925..5e16e350 100644 --- a/pages/api/website/[id]/metrics.js +++ b/pages/api/website/[id]/metrics.js @@ -2,7 +2,7 @@ import { getPageviewMetrics, getSessionMetrics, getWebsiteById } from 'lib/queri import { ok, methodNotAllowed, unauthorized, badRequest } from 'lib/response'; import { allowQuery } from 'lib/auth'; -const sessionColumns = ['browser', 'os', 'device', 'country']; +const sessionColumns = ['browser', 'os', 'device', 'country', 'language']; const pageviewColumns = ['url', 'referrer']; function getTable(type) { @@ -37,7 +37,19 @@ export default async (req, res) => { const endDate = new Date(+end_at); if (sessionColumns.includes(type)) { - const data = await getSessionMetrics(websiteId, startDate, endDate, type, { url }); + let data = await getSessionMetrics(websiteId, startDate, endDate, type, { url }); + + if (type === 'language') { + let combined = {}; + + for (let { x, y } of data) { + x = String(x).toLowerCase().split('-')[0]; + if (!combined[x]) combined[x] = { x, y }; + else combined[x].y += y; + } + + data = Object.values(combined); + } return ok(res, data); } diff --git a/public/language/en-US.json b/public/language/en-US.json new file mode 100644 index 00000000..0a003d33 --- /dev/null +++ b/public/language/en-US.json @@ -0,0 +1,184 @@ +{ + "ab": "Abkhaz", + "aa": "Afar", + "af": "Afrikaans", + "ak": "Akan", + "sq": "Albanian", + "am": "Amharic", + "ar": "Arabic", + "an": "Aragonese", + "hy": "Armenian", + "as": "Assamese", + "av": "Avaric", + "ae": "Avestan", + "ay": "Aymara", + "az": "Azerbaijani", + "bm": "Bambara", + "ba": "Bashkir", + "eu": "Basque", + "be": "Belarusian", + "bn": "Bengali", + "bh": "Bihari", + "bi": "Bislama", + "bs": "Bosnian", + "br": "Breton", + "bg": "Bulgarian", + "my": "Burmese", + "ca": "Catalan; Valencian", + "ch": "Chamorro", + "ce": "Chechen", + "ny": "Chichewa; Chewa; Nyanja", + "zh": "Chinese", + "cv": "Chuvash", + "kw": "Cornish", + "co": "Corsican", + "cr": "Cree", + "hr": "Croatian", + "cs": "Czech", + "da": "Danish", + "dv": "Divehi; Dhivehi; Maldivian;", + "nl": "Dutch", + "en": "English", + "eo": "Esperanto", + "et": "Estonian", + "ee": "Ewe", + "fo": "Faroese", + "fj": "Fijian", + "fi": "Finnish", + "fr": "French", + "ff": "Fula; Fulah; Pulaar; Pular", + "gl": "Galician", + "ka": "Georgian", + "de": "German", + "el": "Greek, Modern", + "gn": "Guaraní", + "gu": "Gujarati", + "ht": "Haitian; Haitian Creole", + "ha": "Hausa", + "he": "Hebrew (modern)", + "hz": "Herero", + "hi": "Hindi", + "ho": "Hiri Motu", + "hu": "Hungarian", + "ia": "Interlingua", + "id": "Indonesian", + "ie": "Interlingue", + "ga": "Irish", + "ig": "Igbo", + "ik": "Inupiaq", + "io": "Ido", + "is": "Icelandic", + "it": "Italian", + "iu": "Inuktitut", + "ja": "Japanese", + "jv": "Javanese", + "kl": "Kalaallisut, Greenlandic", + "kn": "Kannada", + "kr": "Kanuri", + "ks": "Kashmiri", + "kk": "Kazakh", + "km": "Khmer", + "ki": "Kikuyu, Gikuyu", + "rw": "Kinyarwanda", + "ky": "Kirghiz, Kyrgyz", + "kv": "Komi", + "kg": "Kongo", + "ko": "Korean", + "ku": "Kurdish", + "kj": "Kwanyama, Kuanyama", + "la": "Latin", + "lb": "Luxembourgish, Letzeburgesch", + "lg": "Luganda", + "li": "Limburgish, Limburgan, Limburger", + "ln": "Lingala", + "lo": "Lao", + "lt": "Lithuanian", + "lu": "Luba-Katanga", + "lv": "Latvian", + "gv": "Manx", + "mk": "Macedonian", + "mg": "Malagasy", + "ms": "Malay", + "ml": "Malayalam", + "mt": "Maltese", + "mi": "Māori", + "mr": "Marathi (Marāṭhī)", + "mh": "Marshallese", + "mn": "Mongolian", + "na": "Nauru", + "nv": "Navajo, Navaho", + "nb": "Norwegian Bokmål", + "nd": "North Ndebele", + "ne": "Nepali", + "ng": "Ndonga", + "nn": "Norwegian Nynorsk", + "no": "Norwegian", + "ii": "Nuosu", + "nr": "South Ndebele", + "oc": "Occitan", + "oj": "Ojibwe, Ojibwa", + "cu": "Old Church Slavonic, Church Slavic, Church Slavonic, Old Bulgarian, Old Slavonic", + "om": "Oromo", + "or": "Oriya", + "os": "Ossetian, Ossetic", + "pa": "Panjabi, Punjabi", + "pi": "Pāli", + "fa": "Persian", + "pl": "Polish", + "ps": "Pashto, Pushto", + "pt": "Portuguese", + "qu": "Quechua", + "rm": "Romansh", + "rn": "Kirundi", + "ro": "Romanian, Moldavian, Moldovan", + "ru": "Russian", + "sa": "Sanskrit (Saṁskṛta)", + "sc": "Sardinian", + "sd": "Sindhi", + "se": "Northern Sami", + "sm": "Samoan", + "sg": "Sango", + "sr": "Serbian", + "gd": "Scottish Gaelic; Gaelic", + "sn": "Shona", + "si": "Sinhala, Sinhalese", + "sk": "Slovak", + "sl": "Slovene", + "so": "Somali", + "st": "Southern Sotho", + "es": "Spanish; Castilian", + "su": "Sundanese", + "sw": "Swahili", + "ss": "Swati", + "sv": "Swedish", + "ta": "Tamil", + "te": "Telugu", + "tg": "Tajik", + "th": "Thai", + "ti": "Tigrinya", + "bo": "Tibetan Standard, Tibetan, Central", + "tk": "Turkmen", + "tl": "Tagalog", + "tn": "Tswana", + "to": "Tonga (Tonga Islands)", + "tr": "Turkish", + "ts": "Tsonga", + "tt": "Tatar", + "tw": "Twi", + "ty": "Tahitian", + "ug": "Uighur, Uyghur", + "uk": "Ukrainian", + "ur": "Urdu", + "uz": "Uzbek", + "ve": "Venda", + "vi": "Vietnamese", + "vo": "Volapük", + "wa": "Walloon", + "cy": "Welsh", + "wo": "Wolof", + "fy": "Western Frisian", + "xh": "Xhosa", + "yi": "Yiddish", + "yo": "Yoruba", + "za": "Zhuang, Chuang" +} \ No newline at end of file From 9a326a33a0b8dfd737f0af4ba7ce83d35ca93e01 Mon Sep 17 00:00:00 2001 From: Chris Walsh Date: Wed, 1 Dec 2021 19:32:45 -0800 Subject: [PATCH 2/3] Add languages table to metrics grid --- components/metrics/LanguagesTable.js | 31 ++++++++++++++++++++++++++++ components/metrics/MetricsTable.js | 6 +++++- components/pages/WebsiteDetails.js | 9 +++++++- 3 files changed, 44 insertions(+), 2 deletions(-) create mode 100644 components/metrics/LanguagesTable.js diff --git a/components/metrics/LanguagesTable.js b/components/metrics/LanguagesTable.js new file mode 100644 index 00000000..2b6cd868 --- /dev/null +++ b/components/metrics/LanguagesTable.js @@ -0,0 +1,31 @@ +import React from 'react'; +import MetricsTable from './MetricsTable'; +import { percentFilter } from 'lib/filters'; +import { FormattedMessage } from 'react-intl'; +import useLanguageNames from 'hooks/useLanguageNames'; +import useLocale from 'hooks/useLocale'; + +export default function LanguagesTable({ websiteId, onDataLoad, ...props }) { + const { locale } = useLocale(); + const languageNames = useLanguageNames(locale); + + function renderLabel({ x }) { + return ( +
+ {languageNames[x] ?? }{' '} +
+ ); + } + + return ( + } + type="language" + metric={} + websiteId={websiteId} + onDataLoad={data => onDataLoad?.(percentFilter(data))} + renderLabel={renderLabel} + /> + ); +} diff --git a/components/metrics/MetricsTable.js b/components/metrics/MetricsTable.js index 95eb00c3..608e716d 100644 --- a/components/metrics/MetricsTable.js +++ b/components/metrics/MetricsTable.js @@ -23,6 +23,7 @@ export default function MetricsTable({ filterOptions, limit, onDataLoad, + maxHeight = null, ...props }) { const shareToken = useShareToken(); @@ -62,7 +63,10 @@ export default function MetricsTable({ }, [data, error, dataFilter, filterOptions]); return ( -
+
{!data && loading && } {error && } {data && !error && } diff --git a/components/pages/WebsiteDetails.js b/components/pages/WebsiteDetails.js index a8442ea1..de8c8f06 100644 --- a/components/pages/WebsiteDetails.js +++ b/components/pages/WebsiteDetails.js @@ -16,6 +16,7 @@ import BrowsersTable from '../metrics/BrowsersTable'; import OSTable from '../metrics/OSTable'; import DevicesTable from '../metrics/DevicesTable'; import CountriesTable from '../metrics/CountriesTable'; +import LanguagesTable from '../metrics/LanguagesTable'; import EventsTable from '../metrics/EventsTable'; import EventsChart from '../metrics/EventsChart'; import useFetch from 'hooks/useFetch'; @@ -30,6 +31,7 @@ const views = { os: OSTable, device: DevicesTable, country: CountriesTable, + language: LanguagesTable, event: EventsTable, }; @@ -82,6 +84,10 @@ export default function WebsiteDetails({ websiteId }) { label: , value: resolve({ view: 'country' }), }, + { + label: , + value: resolve({ view: 'language' }), + }, { label: , value: resolve({ view: 'event' }), @@ -147,7 +153,8 @@ export default function WebsiteDetails({ websiteId }) { - + + 0 })}> From 77255530977484c1a6c58450f113b2150aa596c1 Mon Sep 17 00:00:00 2001 From: Chris Walsh Date: Fri, 17 Dec 2021 18:25:07 -0800 Subject: [PATCH 3/3] Remove languages table on main metrics page --- components/metrics/MetricsTable.js | 6 +----- components/pages/WebsiteDetails.js | 3 +-- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/components/metrics/MetricsTable.js b/components/metrics/MetricsTable.js index 608e716d..95eb00c3 100644 --- a/components/metrics/MetricsTable.js +++ b/components/metrics/MetricsTable.js @@ -23,7 +23,6 @@ export default function MetricsTable({ filterOptions, limit, onDataLoad, - maxHeight = null, ...props }) { const shareToken = useShareToken(); @@ -63,10 +62,7 @@ export default function MetricsTable({ }, [data, error, dataFilter, filterOptions]); return ( -
+
{!data && loading && } {error && } {data && !error && } diff --git a/components/pages/WebsiteDetails.js b/components/pages/WebsiteDetails.js index de8c8f06..876fbfc4 100644 --- a/components/pages/WebsiteDetails.js +++ b/components/pages/WebsiteDetails.js @@ -153,8 +153,7 @@ export default function WebsiteDetails({ websiteId }) { - - + 0 })}>