[APP-718] Improvements and fixes to language handling (#931)
* Add locale helpers for narrowing languages * Add a translate link to posts in a different language * Update language filtering to use narrowing when multiple declared * Fix a few more RTL layout cases * Fix types
This commit is contained in:
parent
48844aa4c7
commit
ed5a88d9d8
9 changed files with 174 additions and 88 deletions
81
src/locale/helpers.ts
Normal file
81
src/locale/helpers.ts
Normal file
|
@ -0,0 +1,81 @@
|
|||
import {AppBskyFeedDefs, AppBskyFeedPost} from '@atproto/api'
|
||||
import lande from 'lande'
|
||||
import {hasProp} from 'lib/type-guards'
|
||||
import * as bcp47Match from 'bcp-47-match'
|
||||
import {LANGUAGES_MAP_CODE2, LANGUAGES_MAP_CODE3} from './languages'
|
||||
|
||||
export function code2ToCode3(lang: string): string {
|
||||
if (lang.length === 2) {
|
||||
return LANGUAGES_MAP_CODE2[lang]?.code3 || lang
|
||||
}
|
||||
return lang
|
||||
}
|
||||
|
||||
export function code3ToCode2(lang: string): string {
|
||||
if (lang.length === 3) {
|
||||
return LANGUAGES_MAP_CODE3[lang]?.code2 || lang
|
||||
}
|
||||
return lang
|
||||
}
|
||||
|
||||
export function getPostLanguage(
|
||||
post: AppBskyFeedDefs.PostView,
|
||||
): string | undefined {
|
||||
let candidates: string[] = []
|
||||
let postText: string = ''
|
||||
if (hasProp(post.record, 'text') && typeof post.record.text === 'string') {
|
||||
postText = post.record.text
|
||||
}
|
||||
|
||||
if (
|
||||
AppBskyFeedPost.isRecord(post.record) &&
|
||||
hasProp(post.record, 'langs') &&
|
||||
Array.isArray(post.record.langs)
|
||||
) {
|
||||
candidates = post.record.langs
|
||||
}
|
||||
|
||||
// if there's only one declared language, use that
|
||||
if (candidates?.length === 1) {
|
||||
return candidates[0]
|
||||
}
|
||||
|
||||
// no text? can't determine
|
||||
if (postText.trim().length === 0) {
|
||||
return undefined
|
||||
}
|
||||
|
||||
// run the language model
|
||||
let langsProbabilityMap = lande(postText)
|
||||
|
||||
// filter down using declared languages
|
||||
if (candidates?.length) {
|
||||
langsProbabilityMap = langsProbabilityMap.filter(
|
||||
([lang, _probability]: [string, number]) => {
|
||||
return candidates.includes(code3ToCode2(lang))
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
if (langsProbabilityMap[0]) {
|
||||
return code3ToCode2(langsProbabilityMap[0][0])
|
||||
}
|
||||
}
|
||||
|
||||
export function isPostInLanguage(
|
||||
post: AppBskyFeedDefs.PostView,
|
||||
targetLangs: string[],
|
||||
): boolean {
|
||||
const lang = getPostLanguage(post)
|
||||
if (!lang) {
|
||||
// the post has no text, so we just say "yes" for now
|
||||
return true
|
||||
}
|
||||
return bcp47Match.basicFilter(lang, targetLangs).length > 0
|
||||
}
|
||||
|
||||
export function getTranslatorLink(lang: string, text: string): string {
|
||||
return encodeURI(
|
||||
`https://translate.google.com/?sl=auto&tl=${lang}&text=${text}`,
|
||||
)
|
||||
}
|
|
@ -555,3 +555,7 @@ export const LANGUAGES_MAP_CODE2 = Object.fromEntries(
|
|||
export const LANGUAGES_MAP_CODE3 = Object.fromEntries(
|
||||
LANGUAGES.map(lang => [lang.code3, lang]),
|
||||
)
|
||||
// some additional manual mappings (not clear if these should be in the "official" mappings)
|
||||
if (LANGUAGES_MAP_CODE2.fa) {
|
||||
LANGUAGES_MAP_CODE3.pes = LANGUAGES_MAP_CODE2.fa
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue