From 66ade01c4d0ff3862772a79e984b786b5ba3029e Mon Sep 17 00:00:00 2001 From: Yasuaki Uechi Date: Mon, 31 Aug 2020 09:44:05 +0900 Subject: [PATCH] feat: add Google Play Store --- api/services/playstore/[query].ts | 37 ++++++++++ public/locales/de/translation.json | 70 +++++++++---------- public/locales/en/translation.json | 71 ++++++++++---------- public/locales/fr/translation.json | 70 +++++++++---------- public/locales/ja/translation.json | 70 +++++++++---------- public/locales/zh-Hans/translation.json | 70 +++++++++---------- public/locales/zh-Hant/translation.json | 70 +++++++++---------- src/components/cards/index.tsx | 2 + src/components/cards/providers/PlayStore.tsx | 52 ++++++++++++++ src/util/i18n.ts | 2 +- 10 files changed, 303 insertions(+), 211 deletions(-) create mode 100644 api/services/playstore/[query].ts create mode 100644 src/components/cards/providers/PlayStore.tsx diff --git a/api/services/playstore/[query].ts b/api/services/playstore/[query].ts new file mode 100644 index 0000000..08eafe7 --- /dev/null +++ b/api/services/playstore/[query].ts @@ -0,0 +1,37 @@ +import { send, sendError, fetch } from '../../../util/http'; +import { NowRequest, NowResponse } from '@vercel/node'; + +export default async function handler( + req: NowRequest, + res: NowResponse +): Promise { + const { query } = req.query; + + if (!query || typeof query !== 'string') { + return sendError(res, new Error('No query given')); + } + + try { + const responseText = await fetch( + `https://play.google.com/store/search?c=apps&q=${encodeURIComponent( + query + )}`, + 'GET' + ).then((res) => res.text()); + const response = JSON.parse( + responseText.match( + /AF_initDataCallback.+?hash: '5'.+?data:([\w\W]+?), sideChannel/m + )[1] + ); + const apps = response[0][1][0][0][0].map((entry) => ({ + id: entry[12][0], + name: entry[2], + author: entry[4][0][0][0], + rating: entry[6][0][2][1][1], + url: 'https://play.google.com' + entry[9][4][2], + })); + send(res, { result: apps.slice(0, 10) }); + } catch (err) { + sendError(res, err); + } +} diff --git a/public/locales/de/translation.json b/public/locales/de/translation.json index ffd0f2b..e61927e 100644 --- a/public/locales/de/translation.json +++ b/public/locales/de/translation.json @@ -1,52 +1,52 @@ { - "title": "Schnapp dir einen guten Namen für deine neue App", + "about": "Zusammenfassung", + "available": "Verfügbar", + "blog": "Blog-Artikel", + "community": "Gemeinschaft", + "contributors": "Mitwirkende", + "countryCode": "de", "description": "Überprüfen Sie sofort die Verfügbarkeit Ihres neuen Anwendungsnamens in allen wichtigen Registern.", + "gettingStarted": "Fertig werden", + "gettingStartedWithExample": "Untersuche namae", + "issues": "Issues", + "language": "Sprache", + "noResult": "Kein Ergebnis", "placeholder": "suchen", + "pressEnterToSearch": "Drücken Sie die Eingabetaste, um zu suchen", "providers": { + "appStore": "App Store", "domains": "Domänen", + "firebase": "Firebase", "github": "GitHub Organisation", + "githubSearch": "GitHub Repository", "gitlab": "GitLab", + "google": "Google-Suche", + "heroku": "Heroku", + "homebrew": "Homebrew", + "instagram": "Instagram", + "jsorg": "js.org", + "linux": "Linux", + "netlify": "Netlify", + "now": "Vercel", "npm": "npm", + "nta": "Firma (JP)", + "ocaml": "OCaml", "pypi": "PyPI", "rubygems": "RubyGems", "rust": "Rust", - "homebrew": "Homebrew", - "linux": "Linux", - "instagram": "Instagram", - "twitter": "Twitter", - "slack": "Slack", "s3": "AWS S3", - "jsorg": "js.org", - "githubSearch": "GitHub Repository", - "appStore": "App Store", - "google": "Google-Suche", + "slack": "Slack", "spectrum": "Spectrum", - "heroku": "Heroku", - "now": "Vercel", - "netlify": "Netlify", - "nta": "Firma (JP)", - "ocaml": "OCaml", - "firebase": "Firebase" + "twitter": "Twitter" }, - "uniqueness": { - "high": "Ziemlich einzigartig", - "moderate": "Mäßig einzigartig", - "low": "Typisch", - "description": "UNIQ zeigt, wie eindeutig der Name ist (0 bis 100)" - }, - "countryCode": "de", - "try": "Wie wäre es mit?", "showMore": "Zeig mehr", - "noResult": "Kein Ergebnis", - "gettingStarted": "Fertig werden", - "gettingStartedWithExample": "Untersuche namae", - "pressEnterToSearch": "Drücken Sie die Eingabetaste, um zu suchen", - "available": "Verfügbar", + "title": "Schnapp dir einen guten Namen für deine neue App", + "try": "Wie wäre es mit?", "unavailable": "Nicht verfügbar", - "language": "Sprache", - "community": "Gemeinschaft", - "about": "Zusammenfassung", - "contributors": "Mitwirkende", - "issues": "Issues", - "blog": "Blog-Artikel" + "uniqueness": { + "description": "UNIQ zeigt, wie eindeutig der Name ist (0 bis 100)", + "high": "Ziemlich einzigartig", + "low": "Typisch", + "moderate": "Mäßig einzigartig" + } } diff --git a/public/locales/en/translation.json b/public/locales/en/translation.json index 355e663..f4ee280 100644 --- a/public/locales/en/translation.json +++ b/public/locales/en/translation.json @@ -1,52 +1,53 @@ { - "title": "Grab a slick name for your new app", + "about": "About", + "available": "Available", + "blog": "Blog Article", + "community": "Community", + "contributors": "Contributors", + "countryCode": "us", "description": "Check availability for your new app name ideas across major registries at once.", + "gettingStarted": "Getting Started", + "gettingStartedWithExample": "Try with namae", + "issues": "Issues", + "language": "Language", + "noResult": "No Result", "placeholder": "search", + "pressEnterToSearch": "Press Enter to search", "providers": { + "appStore": "App Store", "domains": "Domains", + "firebase": "Firebase", "github": "GitHub Organization", + "githubSearch": "GitHub Repository", "gitlab": "GitLab", + "google": "Google Search", + "heroku": "Heroku", + "homebrew": "Homebrew", + "instagram": "Instagram", + "jsorg": "js.org", + "linux": "Linux", + "netlify": "Netlify", + "now": "Vercel", "npm": "npm", + "nta": "Company (JP)", + "ocaml": "OCaml", + "playStore": "Google Play Store", "pypi": "PyPI", "rubygems": "RubyGems", "rust": "Rust", - "homebrew": "Homebrew", - "linux": "Linux", - "instagram": "Instagram", - "twitter": "Twitter", - "slack": "Slack", "s3": "AWS S3", - "jsorg": "js.org", - "githubSearch": "GitHub Repository", - "appStore": "App Store", - "google": "Google Search", + "slack": "Slack", "spectrum": "Spectrum", - "heroku": "Heroku", - "now": "Vercel", - "netlify": "Netlify", - "nta": "Company (JP)", - "ocaml": "OCaml", - "firebase": "Firebase" + "twitter": "Twitter" }, - "uniqueness": { - "high": "Pretty unique", - "moderate": "Moderately unique", - "low": "Typical", - "description": "UNIQ shows how unique the name is (0 to 100)" - }, - "countryCode": "us", - "try": "How about this?", "showMore": "show more", - "noResult": "No Result", - "gettingStarted": "Getting Started", - "gettingStartedWithExample": "Try with namae", - "pressEnterToSearch": "Press Enter to search", - "available": "Available", + "title": "Grab a slick name for your new app", + "try": "How about this?", "unavailable": "Unavailable", - "language": "Language", - "community": "Community", - "about": "About", - "contributors": "Contributors", - "issues": "Issues", - "blog": "Blog Article" + "uniqueness": { + "description": "UNIQ shows how unique the name is (0 to 100)", + "high": "Pretty unique", + "low": "Typical", + "moderate": "Moderately unique" + } } diff --git a/public/locales/fr/translation.json b/public/locales/fr/translation.json index e2b72f0..e1d2028 100644 --- a/public/locales/fr/translation.json +++ b/public/locales/fr/translation.json @@ -1,52 +1,52 @@ { - "title": "Trouvez un nom original pour votre nouvelle application", + "about": "À propos", + "available": "Disponible", + "blog": "Article de Blog", + "community": "Communauté", + "contributors": "Contributeurs", + "countryCode": "fr", "description": "Vérifiez immédiatement la disponibilité de vos nouvelles idées de noms d'applications dans les principaux registres.", + "gettingStarted": "Pour commencer", + "gettingStartedWithExample": "Essayez avec namae", + "issues": "Issues", + "language": "Langue", + "noResult": "Pas de résultat", "placeholder": "rechercher", + "pressEnterToSearch": "Appuyez sur la touche Entrée pour effectuer une recherche", "providers": { + "appStore": "App Store", "domains": "Domaines", + "firebase": "Firebase", "github": "Organisation GitHub", + "githubSearch": "Dépôt GitHub", "gitlab": "GitLab", + "google": "Recherche Google", + "heroku": "Heroku", + "homebrew": "Homebrew", + "instagram": "Instagram", + "jsorg": "js.org", + "linux": "Linux", + "netlify": "Netlify", + "now": "Vercel", "npm": "npm", + "nta": "Company (JP)", + "ocaml": "OCaml", "pypi": "PyPI", "rubygems": "RubyGems", "rust": "Rust", - "homebrew": "Homebrew", - "linux": "Linux", - "instagram": "Instagram", - "twitter": "Twitter", - "slack": "Slack", "s3": "AWS S3", - "jsorg": "js.org", - "githubSearch": "Dépôt GitHub", - "appStore": "App Store", - "google": "Recherche Google", + "slack": "Slack", "spectrum": "Spectrum", - "heroku": "Heroku", - "now": "Vercel", - "netlify": "Netlify", - "nta": "Company (JP)", - "ocaml": "OCaml", - "firebase": "Firebase" + "twitter": "Twitter" }, - "uniqueness": { - "high": "Plutôt unique", - "moderate": "Modérément unique", - "low": "Typique", - "description": "L'UNIQ indique à quel point le nom est unique (0 à 100)" - }, - "countryCode": "fr", - "try": "Que pensez-vous de cela ?", "showMore": "afficher plus", - "noResult": "Pas de résultat", - "gettingStarted": "Pour commencer", - "gettingStartedWithExample": "Essayez avec namae", - "pressEnterToSearch": "Appuyez sur la touche Entrée pour effectuer une recherche", - "available": "Disponible", + "title": "Trouvez un nom original pour votre nouvelle application", + "try": "Que pensez-vous de cela ?", "unavailable": "Indisponible", - "language": "Langue", - "community": "Communauté", - "about": "À propos", - "contributors": "Contributeurs", - "issues": "Issues", - "blog": "Article de Blog" + "uniqueness": { + "description": "L'UNIQ indique à quel point le nom est unique (0 à 100)", + "high": "Plutôt unique", + "low": "Typique", + "moderate": "Modérément unique" + } } diff --git a/public/locales/ja/translation.json b/public/locales/ja/translation.json index 4e2942e..2998057 100644 --- a/public/locales/ja/translation.json +++ b/public/locales/ja/translation.json @@ -1,52 +1,52 @@ { - "title": "唯一無二の名前を見つける", + "about": "概要", + "available": "取得できます", + "blog": "ブログ", + "community": "コミュニティ", + "contributors": "貢献者", + "countryCode": "jp", "description": "namae はあなたのアプリ、ライブラリ、組織に素敵な名前をつけるお手伝いをします。", + "gettingStarted": "はじめる", + "gettingStartedWithExample": "namae を調べる", + "issues": "Issues", + "language": "言語", + "noResult": "該当なし", "placeholder": "調べる", + "pressEnterToSearch": "エンターキーで検索", "providers": { + "appStore": "App Store", "domains": "ドメイン", + "firebase": "Firebase", "github": "GitHub Organization", + "githubSearch": "GitHub リポジトリ", "gitlab": "GitLab", + "google": "Google 検索", + "heroku": "Heroku", + "homebrew": "Homebrew", + "instagram": "Instagram", + "jsorg": "js.org", + "linux": "Linux", + "netlify": "Netlify", + "now": "Vercel", "npm": "npm", + "nta": "法人", + "ocaml": "OCaml", "pypi": "PyPI", "rubygems": "RubyGems", "rust": "Rust", - "homebrew": "Homebrew", - "linux": "Linux", - "instagram": "Instagram", - "twitter": "Twitter", - "slack": "Slack", "s3": "AWS S3", - "jsorg": "js.org", - "githubSearch": "GitHub リポジトリ", - "appStore": "App Store", - "google": "Google 検索", + "slack": "Slack", "spectrum": "Spectrum", - "heroku": "Heroku", - "now": "Vercel", - "netlify": "Netlify", - "nta": "法人", - "ocaml": "OCaml", - "firebase": "Firebase" + "twitter": "Twitter" }, - "uniqueness": { - "high": "超ユニーク", - "moderate": "そこそこユニーク", - "low": "普通", - "description": "UNIQ は名前がどれくらいユニークかを示しています(0から100)" - }, - "countryCode": "jp", - "try": "これはどう?", "showMore": "さらに表示", - "noResult": "該当なし", - "gettingStarted": "はじめる", - "gettingStartedWithExample": "namae を調べる", - "pressEnterToSearch": "エンターキーで検索", - "available": "取得できます", + "title": "唯一無二の名前を見つける", + "try": "これはどう?", "unavailable": "取得できません", - "language": "言語", - "community": "コミュニティ", - "about": "概要", - "contributors": "貢献者", - "issues": "Issues", - "blog": "ブログ" + "uniqueness": { + "description": "UNIQ は名前がどれくらいユニークかを示しています(0から100)", + "high": "超ユニーク", + "low": "普通", + "moderate": "そこそこユニーク" + } } diff --git a/public/locales/zh-Hans/translation.json b/public/locales/zh-Hans/translation.json index 84ab17f..e0626a5 100644 --- a/public/locales/zh-Hans/translation.json +++ b/public/locales/zh-Hans/translation.json @@ -1,52 +1,52 @@ { - "title": "为您的新应用取个好听的名字", + "about": "关于", + "available": "可获得", + "blog": "博客", + "community": "社区", + "contributors": "贡献者", + "countryCode": "jp", "description": "namae可让您给您的应用程序、Web服务或组织起一个好名字。", + "gettingStarted": "起步", + "gettingStartedWithExample": "试试 namae", + "issues": "Issues", + "language": "语言", + "noResult": "无结果", "placeholder": "检验", + "pressEnterToSearch": "按Enter键搜索", "providers": { + "appStore": "App Store", "domains": "域名", + "firebase": "Firebase", "github": "GitHub 组织", + "githubSearch": "GitHub 仓库", "gitlab": "GitLab", + "google": "谷歌", + "heroku": "Heroku", + "homebrew": "Homebrew", + "instagram": "Instagram", + "jsorg": "js.org", + "linux": "Linux", + "netlify": "Netlify", + "now": "Vercel", "npm": "npm", + "nta": "在日本的公司", + "ocaml": "OCaml", "pypi": "PyPI", "rubygems": "RubyGems", "rust": "Rust", - "homebrew": "Homebrew", - "linux": "Linux", - "instagram": "Instagram", - "twitter": "推特", - "slack": "Slack", "s3": "AWS S3", - "jsorg": "js.org", - "githubSearch": "GitHub 仓库", - "appStore": "App Store", - "google": "谷歌", + "slack": "Slack", "spectrum": "Spectrum", - "heroku": "Heroku", - "now": "Vercel", - "netlify": "Netlify", - "nta": "在日本的公司", - "ocaml": "OCaml", - "firebase": "Firebase" + "twitter": "推特" }, - "uniqueness": { - "high": "超级独特", - "moderate": "有点独特", - "low": "普通", - "description": "UNIQ表示名称的独特性(0-100)" - }, - "countryCode": "jp", - "try": "这个呢?", "showMore": "更多", - "noResult": "无结果", - "gettingStarted": "起步", - "gettingStartedWithExample": "试试 namae", - "pressEnterToSearch": "按Enter键搜索", - "available": "可获得", + "title": "为您的新应用取个好听的名字", + "try": "这个呢?", "unavailable": "不可获得", - "language": "语言", - "community": "社区", - "about": "关于", - "contributors": "贡献者", - "issues": "Issues", - "blog": "博客" + "uniqueness": { + "description": "UNIQ表示名称的独特性(0-100)", + "high": "超级独特", + "low": "普通", + "moderate": "有点独特" + } } diff --git a/public/locales/zh-Hant/translation.json b/public/locales/zh-Hant/translation.json index b54ab10..b95d236 100644 --- a/public/locales/zh-Hant/translation.json +++ b/public/locales/zh-Hant/translation.json @@ -1,52 +1,52 @@ { - "title": "為您的新應用取個好聽的名字", + "about": "關於", + "available": "可獲得", + "blog": "博客", + "community": "社區", + "contributors": "貢獻者", + "countryCode": "jp", "description": "namae可讓您給您的應用程序、Web服務或組織起一個好名字。", + "gettingStarted": "起步", + "gettingStartedWithExample": "試試 namae", + "issues": "Issues", + "language": "語言", + "noResult": "無結果", "placeholder": "檢驗", + "pressEnterToSearch": "按Enter鍵搜索", "providers": { + "appStore": "App Store", "domains": "域名", + "firebase": "Firebase", "github": "GitHub 組織", + "githubSearch": "GitHub 倉庫", "gitlab": "GitLab", + "google": "谷歌", + "heroku": "Heroku", + "homebrew": "Homebrew", + "instagram": "Instagram", + "jsorg": "js.org", + "linux": "Linux", + "netlify": "Netlify", + "now": "Vercel", "npm": "npm", + "nta": "在日本的公司", + "ocaml": "OCaml", "pypi": "PyPI", "rubygems": "RubyGems", "rust": "Rust", - "homebrew": "Homebrew", - "linux": "Linux", - "instagram": "Instagram", - "twitter": "推特", - "slack": "Slack", "s3": "AWS S3", - "jsorg": "js.org", - "githubSearch": "GitHub 倉庫", - "appStore": "App Store", - "google": "谷歌", + "slack": "Slack", "spectrum": "Spectrum", - "heroku": "Heroku", - "now": "Vercel", - "netlify": "Netlify", - "nta": "在日本的公司", - "ocaml": "OCaml", - "firebase": "Firebase" + "twitter": "推特" }, - "uniqueness": { - "high": "超級獨特", - "moderate": "有點獨特", - "low": "普通", - "description": "UNIQ表示名稱的獨特性(0-100)" - }, - "countryCode": "jp", - "try": "這個呢?", "showMore": "更多", - "noResult": "無結果", - "gettingStarted": "起步", - "gettingStartedWithExample": "試試 namae", - "pressEnterToSearch": "按Enter鍵搜索", - "available": "可獲得", + "title": "為您的新應用取個好聽的名字", + "try": "這個呢?", "unavailable": "不可獲得", - "language": "語言", - "community": "社區", - "about": "關於", - "contributors": "貢獻者", - "issues": "Issues", - "blog": "博客" + "uniqueness": { + "description": "UNIQ表示名稱的獨特性(0-100)", + "high": "超級獨特", + "low": "普通", + "moderate": "有點獨特" + } } diff --git a/src/components/cards/index.tsx b/src/components/cards/index.tsx index 3e7e646..6271137 100644 --- a/src/components/cards/index.tsx +++ b/src/components/cards/index.tsx @@ -18,6 +18,7 @@ import NetlifyCard from './providers/Netlify'; import NpmCard from './providers/Npm'; import NtaCard from './providers/Nta'; import OcamlCard from './providers/Ocaml'; +import PlayStoreCard from './providers/PlayStore'; import PypiCard from './providers/PyPI'; import RubyGemsCard from './providers/RubyGems'; import S3Card from './providers/S3'; @@ -58,6 +59,7 @@ const Index: React.FC<{ query: string }> = ({ query }) => { + {language === 'ja' ? : null} diff --git a/src/components/cards/providers/PlayStore.tsx b/src/components/cards/providers/PlayStore.tsx new file mode 100644 index 0000000..de7ae88 --- /dev/null +++ b/src/components/cards/providers/PlayStore.tsx @@ -0,0 +1,52 @@ +import useFetch from 'fetch-suspense'; +import React from 'react'; +import { useTranslation } from 'react-i18next'; +import { FaInfoCircle } from 'react-icons/fa'; +import { IoMdAppstore } from 'react-icons/io'; +import { Card, Result } from '../core'; + +const Search: React.FC<{ query: string }> = ({ query }) => { + const { t } = useTranslation(); + const response = useFetch( + `/api/services/playstore/${encodeURIComponent(query)}}` + ) as { + result: Array<{ + id: string; + name: string; + author: string; + rating: number; + url: string; + }>; + }; + const apps = response.result; + + return ( + <> + {apps && apps.length > 0 ? ( + apps.map((app) => ( + } + key={app.id} + /> + )) + ) : ( + } /> + )} + + ); +}; + +const PlayStoreCard: React.FC<{ query: string }> = ({ query }) => { + const { t } = useTranslation(); + + return ( + + + + ); +}; + +export default PlayStoreCard; diff --git a/src/util/i18n.ts b/src/util/i18n.ts index 90bea51..2b5cd32 100644 --- a/src/util/i18n.ts +++ b/src/util/i18n.ts @@ -5,7 +5,7 @@ import XHR from 'i18next-xhr-backend'; import LanguageDetector from 'i18next-browser-languagedetector'; import { initReactI18next } from 'react-i18next'; -const TRANSLATION_VERSION = '3'; +const TRANSLATION_VERSION = '4'; i18n .use(Backend)