commit
d5ab8bf53f
|
@ -3,8 +3,7 @@
|
|||
html,
|
||||
body {
|
||||
margin: 0;
|
||||
font-family: "Segoe UI", "Source Han Sans SC Regular", "Microsoft YaHei",
|
||||
sans-serif;
|
||||
font-family: "Segoe UI", "Source Han Sans Regular", sans-serif;
|
||||
}
|
||||
body {
|
||||
padding: 12px 96px 32px;
|
||||
|
|
|
@ -49,12 +49,27 @@ body.darwin {
|
|||
html,
|
||||
body {
|
||||
background-color: transparent;
|
||||
font-family: "Segoe UI", "Source Han Sans SC Regular", "Microsoft YaHei",
|
||||
sans-serif;
|
||||
font-family: "Segoe UI", "Source Han Sans Regular", sans-serif;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
margin: 0;
|
||||
}
|
||||
body:lang(zh-CN) {
|
||||
font-family: "Segoe UI", "Source Han Sans SC Regular", "Microsoft YaHei",
|
||||
sans-serif;
|
||||
}
|
||||
body:lang(zh-TW) {
|
||||
font-family: "Segoe UI", "Source Han Sans TC Regular", "Microsoft JhengHei",
|
||||
sans-serif;
|
||||
}
|
||||
body:lang(ja) {
|
||||
font-family: "Segoe UI", "Source Han Sans JP Regular", "Yu Gothic UI",
|
||||
sans-serif;
|
||||
}
|
||||
body:lang(ko) {
|
||||
font-family: "Segoe UI", "Source Han Sans KR Regular", "Malgun Gothic",
|
||||
sans-serif;
|
||||
}
|
||||
body.win32,
|
||||
body.linux {
|
||||
background-color: var(--neutralLighterAlt);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
appId: DevHYLiu.FluentReader
|
||||
buildVersion: 25
|
||||
buildVersion: 26
|
||||
productName: Fluent Reader
|
||||
copyright: Copyright © 2020 Haoyuan Liu
|
||||
files:
|
||||
|
@ -29,6 +29,9 @@ mac:
|
|||
- it
|
||||
- nl
|
||||
- ko
|
||||
- ru
|
||||
- pt_BR
|
||||
- pt_PT
|
||||
minimumSystemVersion: 10.14.0
|
||||
mas:
|
||||
entitlements: build/entitlements.mas.plist
|
||||
|
|
|
@ -26,6 +26,9 @@ mac:
|
|||
- it
|
||||
- nl
|
||||
- ko
|
||||
- ru
|
||||
- pt_BR
|
||||
- pt_PT
|
||||
win:
|
||||
target:
|
||||
- nsis
|
||||
|
@ -49,6 +52,9 @@ appx:
|
|||
- it
|
||||
- nl
|
||||
- ko
|
||||
- ru
|
||||
- pt-BR
|
||||
- pt-PT
|
||||
showNameOnTiles: true
|
||||
setBuildNumber: true
|
||||
nsis:
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "fluent-reader",
|
||||
"version": "1.1.0",
|
||||
"version": "1.1.1",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "fluent-reader",
|
||||
"version": "1.1.0",
|
||||
"version": "1.1.1",
|
||||
"description": "Modern desktop RSS reader",
|
||||
"main": "./dist/electron.js",
|
||||
"scripts": {
|
||||
|
|
|
@ -328,17 +328,22 @@ class Article extends React.Component<ArticleProps, ArticleState> {
|
|||
}
|
||||
loadFull = async () => {
|
||||
this.setState({ fullContent: "", loaded: false, error: false })
|
||||
const link = this.props.item.link
|
||||
try {
|
||||
const result = await fetch(this.props.item.link)
|
||||
const result = await fetch(link)
|
||||
if (!result || !result.ok) throw new Error()
|
||||
const html = await decodeFetchResponse(result, true)
|
||||
this.setState({ fullContent: html })
|
||||
if (link === this.props.item.link) {
|
||||
this.setState({ fullContent: html })
|
||||
}
|
||||
} catch {
|
||||
this.setState({
|
||||
loaded: true,
|
||||
error: true,
|
||||
errorDescription: "MERCURY_PARSER_FAILURE",
|
||||
})
|
||||
if (link === this.props.item.link) {
|
||||
this.setState({
|
||||
loaded: true,
|
||||
error: true,
|
||||
errorDescription: "MERCURY_PARSER_FAILURE",
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -467,7 +472,8 @@ class Article extends React.Component<ArticleProps, ArticleState> {
|
|||
className={this.state.error ? "error" : ""}
|
||||
key={
|
||||
this.props.item._id +
|
||||
(this.state.loadWebpage ? "_" : "")
|
||||
(this.state.loadWebpage ? "_" : "") +
|
||||
(this.state.loadFull ? "__" : "")
|
||||
}
|
||||
src={
|
||||
this.state.loadWebpage
|
||||
|
|
|
@ -23,10 +23,15 @@ const CompactCard: React.FunctionComponent<Card.Props> = props => (
|
|||
text={props.item.title}
|
||||
filter={props.filter}
|
||||
title
|
||||
dir={props.source.textDir}
|
||||
/>
|
||||
</span>
|
||||
<span className="snippet">
|
||||
<Highlights text={props.item.snippet} filter={props.filter} />
|
||||
<Highlights
|
||||
text={props.item.snippet}
|
||||
filter={props.filter}
|
||||
dir={props.source.textDir}
|
||||
/>
|
||||
</span>
|
||||
</div>
|
||||
<Time date={props.item.date} />
|
||||
|
|
|
@ -25,10 +25,19 @@ const DefaultCard: React.FunctionComponent<Card.Props> = props => (
|
|||
) : null}
|
||||
<CardInfo source={props.source} item={props.item} />
|
||||
<h3 className="title">
|
||||
<Highlights text={props.item.title} filter={props.filter} title />
|
||||
<Highlights
|
||||
text={props.item.title}
|
||||
filter={props.filter}
|
||||
title
|
||||
dir={props.source.textDir}
|
||||
/>
|
||||
</h3>
|
||||
<p className={"snippet" + (props.item.thumb ? "" : " show")}>
|
||||
<Highlights text={props.item.snippet} filter={props.filter} />
|
||||
<Highlights
|
||||
text={props.item.snippet}
|
||||
filter={props.filter}
|
||||
dir={props.source.textDir}
|
||||
/>
|
||||
</p>
|
||||
</div>
|
||||
)
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
import * as React from "react"
|
||||
import { validateRegex } from "../../scripts/utils"
|
||||
import { FeedFilter, FilterType } from "../../scripts/models/feed"
|
||||
import { SourceTextDirection } from "../../scripts/models/source"
|
||||
|
||||
type HighlightsProps = {
|
||||
text: string
|
||||
filter: FeedFilter
|
||||
title?: boolean
|
||||
dir?: SourceTextDirection
|
||||
}
|
||||
|
||||
const Highlights: React.FunctionComponent<HighlightsProps> = props => {
|
||||
|
@ -57,10 +59,22 @@ const Highlights: React.FunctionComponent<HighlightsProps> = props => {
|
|||
}
|
||||
}
|
||||
|
||||
const testStyle = {
|
||||
direction: "inherit",
|
||||
} as React.CSSProperties
|
||||
if (props.dir === SourceTextDirection.RTL) {
|
||||
testStyle.direction = "rtl"
|
||||
}
|
||||
return (
|
||||
<>
|
||||
{spans.map(([text, flag]) =>
|
||||
flag ? <span className="h">{text}</span> : text
|
||||
flag ? (
|
||||
<div className="h" style={testStyle}>
|
||||
{text}
|
||||
</div>
|
||||
) : (
|
||||
<div style={testStyle}>{text}</div>
|
||||
)
|
||||
)}
|
||||
</>
|
||||
)
|
||||
|
|
|
@ -31,6 +31,7 @@ const ListCard: React.FunctionComponent<Card.Props> = props => (
|
|||
text={props.item.title}
|
||||
filter={props.filter}
|
||||
title
|
||||
dir={props.source.textDir}
|
||||
/>
|
||||
</h3>
|
||||
{Boolean(props.viewConfigs & ViewConfigs.ShowSnippet) && (
|
||||
|
@ -38,6 +39,7 @@ const ListCard: React.FunctionComponent<Card.Props> = props => (
|
|||
<Highlights
|
||||
text={props.item.snippet}
|
||||
filter={props.filter}
|
||||
dir={props.source.textDir}
|
||||
/>
|
||||
</p>
|
||||
)}
|
||||
|
|
|
@ -28,12 +28,14 @@ const MagazineCard: React.FunctionComponent<Card.Props> = props => (
|
|||
text={props.item.title}
|
||||
filter={props.filter}
|
||||
title
|
||||
dir={props.source.textDir}
|
||||
/>
|
||||
</h3>
|
||||
<p className="snippet">
|
||||
<Highlights
|
||||
text={props.item.snippet}
|
||||
filter={props.filter}
|
||||
dir={props.source.textDir}
|
||||
/>
|
||||
</p>
|
||||
</div>
|
||||
|
|
|
@ -135,10 +135,12 @@ class AppTab extends React.Component<AppTabProps, AppTabState> {
|
|||
{ key: "it", text: "Italiano" },
|
||||
{ key: "nl", text: "Nederlands" },
|
||||
{ key: "pt-BR", text: "Português do Brasil" },
|
||||
{ key: "pt-PT", text: "Português de Portugal" },
|
||||
{ key: "fi-FI", text: "Suomi" },
|
||||
{ key: "sv", text: "Svenska" },
|
||||
{ key: "tr", text: "Türkçe" },
|
||||
{ key: "uk", text: "Українська" },
|
||||
{ key: "ru", text: "Русский" },
|
||||
{ key: "ko", text: "한글" },
|
||||
{ key: "ja", text: "日本語" },
|
||||
{ key: "zh-CN", text: "中文(简体)" },
|
||||
|
|
|
@ -18,6 +18,8 @@ Currently, Fluent Reader supports the following languages.
|
|||
| nl | Nederlands | [@Vistaus](https://github.com/Vistaus) |
|
||||
| it | Italiano | [@andrewasd](https://github.com/andrewasd) |
|
||||
| pt-BR | Português do Brasil | [@fabianski7](https://github.com/fabianski7) |
|
||||
| pt-PT | Português de Portugal | [@0x1336](https://github.com/0x1336) |
|
||||
| ko | 한글 | [@1drive](https://github.com/1drive) |
|
||||
| ru | Russian | [@nxblnd](https://github.com/nxblnd) |
|
||||
|
||||
Refer to the repo of [react-intl-universal](https://github.com/alibaba/react-intl-universal) to get started on internationalization.
|
||||
|
|
|
@ -10,9 +10,11 @@ import sv from "./sv.json"
|
|||
import tr from "./tr.json"
|
||||
import it from "./it.json"
|
||||
import uk from "./uk.json"
|
||||
import ru from "./ru.json"
|
||||
import pt_BR from "./pt-BR.json"
|
||||
import fi_FI from "./fi-FI.json"
|
||||
import ko from "./ko.json"
|
||||
import pt_PT from "./pt-PT.json"
|
||||
|
||||
const locales = {
|
||||
"en-US": en_US,
|
||||
|
@ -27,9 +29,11 @@ const locales = {
|
|||
"tr": tr,
|
||||
"it": it,
|
||||
"uk": uk,
|
||||
"ru": ru,
|
||||
"pt-BR": pt_BR,
|
||||
"fi-FI": fi_FI,
|
||||
"ko": ko,
|
||||
"pt-PT": pt_PT,
|
||||
}
|
||||
|
||||
export default locales
|
||||
|
|
|
@ -0,0 +1,241 @@
|
|||
{
|
||||
"allArticles": "Todos os artigos",
|
||||
"add": "Adicionar",
|
||||
"create": "Criar",
|
||||
"icon": "Ícone",
|
||||
"name": "Nome",
|
||||
"openExternal": "Abrir externamente",
|
||||
"emptyName": "Este campo não pode ficar vazio.",
|
||||
"emptyField": "Este campo não pode ficar vazio.",
|
||||
"edit": "Editar",
|
||||
"delete": "Eliminar",
|
||||
"followSystem": "Seguir o sistema",
|
||||
"more": "Mais",
|
||||
"close": "Fechar",
|
||||
"search": "Pesquisar",
|
||||
"loadMore": "Carregar mais",
|
||||
"dangerButton": "Confirmar {action}?",
|
||||
"confirmMarkAll": "Deseja mesmo marcar todos os artigos desta página como lidos?",
|
||||
"confirm": "Confirmar",
|
||||
"cancel": "Cancelar",
|
||||
"default": "Padrão",
|
||||
"time": {
|
||||
"now": "agora",
|
||||
"m": "m",
|
||||
"h": "h",
|
||||
"d": "d",
|
||||
"minute": "{m, plural, =1 {# minuto} other {# minutos}}",
|
||||
"hour": "{h, plural, =1 {# hora} other {# horas}}",
|
||||
"day": "{d, plural, =1 {# dia} other {# dias}}"
|
||||
},
|
||||
"log": {
|
||||
"empty": "Nenhuma notificação",
|
||||
"fetchFailure": "Falha ao carregar a fonte \"{name}\".",
|
||||
"fetchSuccess": "{count, plural, =1 {# Artigo} other {# Artigos}} foram atualizados com sucesso.",
|
||||
"networkError": "Ocorreu um erro na rede.",
|
||||
"parseError": "Ocorreu um erro ao analisar o feed XML.",
|
||||
"syncFailure": "Falha ao sincronizar com o serviço"
|
||||
},
|
||||
"nav": {
|
||||
"menu": "Menu",
|
||||
"refresh": "Atualizar",
|
||||
"markAllRead": "Marcar todos como lidos",
|
||||
"notifications": "Notificações",
|
||||
"view": "Visualização",
|
||||
"settings": "Definições",
|
||||
"minimize": "Minimizar",
|
||||
"maximize": "Maximizar"
|
||||
},
|
||||
"menu": {
|
||||
"close": "Fechar menu",
|
||||
"subscriptions": "Subscrições"
|
||||
},
|
||||
"article": {
|
||||
"error": "Falha ao carregar o artigo.",
|
||||
"reload": "Recarregar?",
|
||||
"empty": "Nenhum artigo",
|
||||
"untitled": "(Sem título)",
|
||||
"hide": "Ocultar artigo",
|
||||
"unhide": "Exibir artigo",
|
||||
"markRead": "Marcar como lido",
|
||||
"markUnread": "Marcar como não lido",
|
||||
"markAbove": "Marcar artigo(s) acima como lido(s)",
|
||||
"markBelow": "Marcar artigo(s) abaixo como não lido(s)",
|
||||
"star": "Marcar como favorito",
|
||||
"unstar": "Remover marcação",
|
||||
"fontSize": "Tamanho da fonte",
|
||||
"loadWebpage": "Carregar página web",
|
||||
"loadFull": "Carregar todo o conteúdo",
|
||||
"notify": "Notificar se atualizado em segundo plano",
|
||||
"dontNotify": "Não notificar",
|
||||
"textDir": "Direção do texto",
|
||||
"LTR": "Esquerda-para-direita",
|
||||
"RTL": "Direita-para-esquerda",
|
||||
"Vertical": "Vertical",
|
||||
"font": "Fonte"
|
||||
},
|
||||
"context": {
|
||||
"share": "Partilhar",
|
||||
"read": "Ler",
|
||||
"copyTitle": "Copiar título",
|
||||
"copyURL": "Copiar link",
|
||||
"copy": "Copiar",
|
||||
"search": "Pesquisar \"{text}\" no {engine}",
|
||||
"view": "Visualizar",
|
||||
"cardView": "Como cartões",
|
||||
"listView": "Em lista",
|
||||
"magazineView": "Como revista",
|
||||
"compactView": "Compacto",
|
||||
"filter": "Filtrar",
|
||||
"unreadOnly": "Apenas não lidos",
|
||||
"starredOnly": "Apenas favoritos",
|
||||
"fullSearch": "Pesquisar em todo o texto",
|
||||
"showHidden": "Exibir artigos ocultos",
|
||||
"manageSources": "Gerir fontes",
|
||||
"saveImageAs": "Guardar imagem como …",
|
||||
"copyImage": "Copiar imagem",
|
||||
"copyImageURL": "Copiar link da imagem",
|
||||
"caseSensitive": "Diferenciar maiúsculas e minúsculas",
|
||||
"showCover": "Mostrar capa",
|
||||
"showSnippet": "Mostrar trecho",
|
||||
"fadeRead": "Desaparecer artigos lidos"
|
||||
},
|
||||
"searchEngine": {
|
||||
"name": "Motor de pesquisa",
|
||||
"google": "Google",
|
||||
"bing": "Bing",
|
||||
"baidu": "Baidu",
|
||||
"duckduckgo": "DuckDuckGo"
|
||||
},
|
||||
"settings": {
|
||||
"writeError": "Ocorreu um erro ao gravar o ficheiro.",
|
||||
"name": "Definições",
|
||||
"fetching": "Atualizando fontes, aguarde por favor …",
|
||||
"exit": "Sair das definições",
|
||||
"sources": "Fontes",
|
||||
"grouping": "Grupos",
|
||||
"rules": "Regras",
|
||||
"service": "Serviço",
|
||||
"app": "Preferências",
|
||||
"about": "Sobre",
|
||||
"version": "Versão",
|
||||
"shortcuts": "Atalhos",
|
||||
"openSource": "Código aberto",
|
||||
"feedback": "Feedback"
|
||||
},
|
||||
"sources": {
|
||||
"serviceWarning": "Fontes importadas ou adicionadas aqui não serão sincronizadas com o seu serviço.",
|
||||
"serviceManaged": "Esta fonte é gerenciada pelo seu serviço.",
|
||||
"untitled": "Fonte",
|
||||
"errorAdd": "Ocorreu um erro ao adicionar a fonte.",
|
||||
"errorParse": "Ocorreu um erro ao analisar o arquivo OPML.",
|
||||
"errorParseHint": "Certifique-se de que o arquivo não esteja corrompido e que esteja codificado com UTF-8.",
|
||||
"errorImport": "Erro ao importar {count, plural, =1 {# fonte} other {# fontes}}.",
|
||||
"exist": "Esta fonte já existe.",
|
||||
"opmlFile": "Ficheiro OPML",
|
||||
"name": "Nome da fonte",
|
||||
"editName": "Editar nome",
|
||||
"fetchFrequency": "Limite da frequência de atualização",
|
||||
"unlimited": "Ilimitado",
|
||||
"openTarget": "Método padrão de carregamento dos artigos",
|
||||
"delete": "Eliminar fonte",
|
||||
"add": "Adicionar fonte",
|
||||
"import": "Importar",
|
||||
"export": "Exportar",
|
||||
"rssText": "Texto completo do RSS",
|
||||
"loadWebpage": "Carregar página web",
|
||||
"inputUrl": "Insira a URL",
|
||||
"badIcon": "Ícone inválido",
|
||||
"badUrl": "URL inválida",
|
||||
"deleteWarning": "A fonte e todos os artigos guardados serão removidos.",
|
||||
"selected": "Fonte selecionada",
|
||||
"selectedMulti": "Múltiplas fontes selecionadas"
|
||||
},
|
||||
"groups": {
|
||||
"exist": "Este grupo já existe.",
|
||||
"type": "Tipo",
|
||||
"group": "Grupo",
|
||||
"source": "Fonte",
|
||||
"capacity": "Capacidade",
|
||||
"exitGroup": "Voltar para os grupos",
|
||||
"deleteSource": "Eliminar do grupo",
|
||||
"sourceHint": "Arraste e solte as fontes para reorganizá-las.",
|
||||
"create": "Criar grupo",
|
||||
"selectedGroup": "Grupo selecionado",
|
||||
"selectedSource": "Fonte selecionada",
|
||||
"enterName": "Insira o nome",
|
||||
"editName": "Editar nome",
|
||||
"deleteGroup": "Eliminar grupo",
|
||||
"chooseGroup": "Selecione um grupo",
|
||||
"addToGroup": "Adicionar a ...",
|
||||
"groupHint": "Clique duplo no grupo para editar as fontes. Arraste e solte para reorganizá-los."
|
||||
},
|
||||
"rules": {
|
||||
"intro": "Marcar artigos automaticamente ou enviar notificações com expressões regulares.",
|
||||
"help": "Saber mais",
|
||||
"source": "Fonte",
|
||||
"selectSource": "Selecionar uma fonte",
|
||||
"new": "Nova regra",
|
||||
"if": "Se",
|
||||
"then": "Então",
|
||||
"title": "Título",
|
||||
"content": "Conteúdo",
|
||||
"fullSearch": "Título ou conteúdo",
|
||||
"creator": "Autor",
|
||||
"match": "corresponde",
|
||||
"notMatch": "não corresponde",
|
||||
"regex": "Expressão regular",
|
||||
"badRegex": "Expressão regular inválida.",
|
||||
"action": "Ações",
|
||||
"selectAction": "Selecionar ações",
|
||||
"hint": "As regras serão aplicadas em ordem. Arraste e solte para reorganizar.",
|
||||
"test": "Testar regras"
|
||||
},
|
||||
"service": {
|
||||
"intro": "Sincronização entre dispositivos com serviços RSS.",
|
||||
"select": "Selecione um serviço",
|
||||
"suggest": "Sugerir um novo serviço",
|
||||
"overwriteWarning": "Fontes locais serão eliminadas se elas existirem no serviço.",
|
||||
"groupsWarning": "Grupos não são automaticamente sincronizados com o serviço.",
|
||||
"rateLimitWarning": "Para evitar limitações do serviço, você precisa criar sua própria chave de API.",
|
||||
"removeAd": "Remover Anuncio",
|
||||
"endpoint": "Endpoint",
|
||||
"username": "Utilizador",
|
||||
"password": "Password",
|
||||
"unchanged": "Inalterado",
|
||||
"fetchLimit": "Limite de sincronização",
|
||||
"fetchLimitNum": "{count} últimos artigos",
|
||||
"importGroups": "Importar grupos",
|
||||
"failure": "Não foi possível conectar ao serviço",
|
||||
"failureHint": "Por favor verifique a configuração do serviço ou o estado da rede.",
|
||||
"fetchUnlimited": "Ilimitado (não recomendado)",
|
||||
"exportToLite": "Exportar para o Fluent Reader Lite"
|
||||
},
|
||||
"app": {
|
||||
"cleanup": "Limpar",
|
||||
"cache": "Limpar cache",
|
||||
"cacheSize": "{size} de dados em cache",
|
||||
"deleteChoices": "Eliminar artigos de ... dias atrás",
|
||||
"confirmDelete": "Eliminar",
|
||||
"daysAgo": "{days, plural, =1 {# dia} other {# dias}} atrás",
|
||||
"deleteAll": "Eliminar todos os artigos",
|
||||
"calculatingSize": "Calculando tamanho...",
|
||||
"itemSize": "Cerca de {size} do armazenamento local é ocupado por artigos",
|
||||
"confirmImport": "Do you really want to import data from the backup file? All current data will be wiped.",
|
||||
"data": "Dados da aplicação",
|
||||
"backup": "Backup",
|
||||
"restore": "Restorar",
|
||||
"frData": "Dados do Fluent Reader",
|
||||
"language": "Idioma",
|
||||
"theme": "Tema",
|
||||
"lightTheme": "Modo claro",
|
||||
"darkTheme": "Modo escuro",
|
||||
"enableProxy": "Ativar proxy",
|
||||
"badUrl": "URL inválida",
|
||||
"pac": "Endereço PAC",
|
||||
"setPac": "Definir PAC",
|
||||
"pacHint": "Para proxies Socks, é recomendado para o PAC retornar \"SOCKS5\" para o proxy-side DNS. Desligar o proxy requer um reinicio.",
|
||||
"fetchInterval": "Intervalo de atualização automática",
|
||||
"never": "Nunca"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,241 @@
|
|||
{
|
||||
"allArticles": "Все статьи",
|
||||
"add": "Добавить",
|
||||
"create": "Создать",
|
||||
"icon": "Иконка",
|
||||
"name": "Название",
|
||||
"openExternal": "Открыть внешней программой",
|
||||
"emptyName": "Это поле не может быть пустым.",
|
||||
"emptyField": "Это поле не может быть пустым.",
|
||||
"edit": "Редактировать",
|
||||
"delete": "Удалить",
|
||||
"followSystem": "Как в системе",
|
||||
"more": "Ещё",
|
||||
"close": "Закрыть",
|
||||
"search": "Поиск",
|
||||
"loadMore": "Загрузить ещё",
|
||||
"dangerButton": "Подтвердить {action}?",
|
||||
"confirmMarkAll": "Вы действительно хотите отметить все статьи на этой странице прочитанными?",
|
||||
"confirm": "Подтвердить",
|
||||
"cancel": "Отмена",
|
||||
"default": "По умолчанию",
|
||||
"time": {
|
||||
"now": "сейчас",
|
||||
"m": "м",
|
||||
"h": "ч",
|
||||
"d": "д",
|
||||
"minute": "{m, plural, =1 {# минута} other {# минут}}",
|
||||
"hour": "{h, plural, =1 {# час} other {# часов}}",
|
||||
"day": "{d, plural, =1 {# день} other {# дней}}"
|
||||
},
|
||||
"log": {
|
||||
"empty": "Нет уведомлений",
|
||||
"fetchFailure": "Не удалось загрузить из источника \"{name}\".",
|
||||
"fetchSuccess": "Успешно {count, plural, =1 {получена # статья} other {получены # статей}}.",
|
||||
"networkError": "Ошибка сети.",
|
||||
"parseError": "Возникла ошибка при разборе XML.",
|
||||
"syncFailure": "Не удалось синхронизировать с сервисом"
|
||||
},
|
||||
"nav": {
|
||||
"menu": "Меню",
|
||||
"refresh": "Обновить",
|
||||
"markAllRead": "Отметить всё прочитанным",
|
||||
"notifications": "Уведомления",
|
||||
"view": "Вид",
|
||||
"settings": "Настройки",
|
||||
"minimize": "Свернуть",
|
||||
"maximize": "Развернуть"
|
||||
},
|
||||
"menu": {
|
||||
"close": "Закрыть меню",
|
||||
"subscriptions": "Подписки"
|
||||
},
|
||||
"article": {
|
||||
"error": "Не удалось загрузить статью.",
|
||||
"reload": "Перезагрузить?",
|
||||
"empty": "Нет статей",
|
||||
"untitled": "(Без названия)",
|
||||
"hide": "Спрятать статью",
|
||||
"unhide": "Показать статью",
|
||||
"markRead": "Отметить как прочитанное",
|
||||
"markUnread": "Отметить как непрочитанное",
|
||||
"markAbove": "Отметить выше как прочитанное",
|
||||
"markBelow": "Отметить ниже как прочитанное",
|
||||
"star": "В избранное",
|
||||
"unstar": "Убрать из избранного",
|
||||
"fontSize": "Размер шрифта",
|
||||
"loadWebpage": "Загрузить веб-страницу",
|
||||
"loadFull": "Загрузить полное содержимое",
|
||||
"notify": "Уведомить, если получено в фоновом режиме",
|
||||
"dontNotify": "Не уведомлять",
|
||||
"textDir": "Направление текста",
|
||||
"LTR": "Слева направо",
|
||||
"RTL": "Справа налево",
|
||||
"Vertical": "Вертикально",
|
||||
"font": "Шрифт"
|
||||
},
|
||||
"context": {
|
||||
"share": "Поделиться",
|
||||
"read": "Читать",
|
||||
"copyTitle": "Копировать заголовок",
|
||||
"copyURL": "Копировать ссылку",
|
||||
"copy": "Копировать",
|
||||
"search": "Искать \"{text}\" в {engine}",
|
||||
"view": "Вид",
|
||||
"cardView": "Карточки",
|
||||
"listView": "Список",
|
||||
"magazineView": "Журнал",
|
||||
"compactView": "Компактный",
|
||||
"filter": "Фильтры",
|
||||
"unreadOnly": "Только непрочитанные",
|
||||
"starredOnly": "Только избранные",
|
||||
"fullSearch": "Поиск по всему тексту",
|
||||
"showHidden": "Показывать скрытые",
|
||||
"manageSources": "Управление источниками",
|
||||
"saveImageAs": "Сохранить изображение как …",
|
||||
"copyImage": "Копировать изображение",
|
||||
"copyImageURL": "Копировать ссылку на изображение",
|
||||
"caseSensitive": "С учётом регистра",
|
||||
"showCover": "Показать обложку",
|
||||
"showSnippet": "Показать отрывок",
|
||||
"fadeRead": "Высветлять прочитанные статьи"
|
||||
},
|
||||
"searchEngine": {
|
||||
"name": "Поисковая система",
|
||||
"google": "Google",
|
||||
"bing": "Bing",
|
||||
"baidu": "Baidu",
|
||||
"duckduckgo": "DuckDuckGo"
|
||||
},
|
||||
"settings": {
|
||||
"writeError": "Произошла ошибка при записи файла.",
|
||||
"name": "Настройки",
|
||||
"fetching": "Обновление источников. Пожалуйста, подождите.",
|
||||
"exit": "Выйти из настроек",
|
||||
"sources": "Источники",
|
||||
"grouping": "Группы",
|
||||
"rules": "Правила",
|
||||
"service": "Сервисы",
|
||||
"app": "Предпочтения",
|
||||
"about": "О программе",
|
||||
"version": "Версия",
|
||||
"shortcuts": "Сочетания клавиш",
|
||||
"openSource": "Открытый исходный код",
|
||||
"feedback": "Обратная связь"
|
||||
},
|
||||
"sources": {
|
||||
"serviceWarning": "Импортированные или добавленные здесь источники не будут синхронизированы с Вашим сервисом.",
|
||||
"serviceManaged": "Этот источник управляется Вашим сервисом.",
|
||||
"untitled": "Источник",
|
||||
"errorAdd": "Возникла ошибка при добавлении источника.",
|
||||
"errorParse": "Возникла ошибка при разборе OPML файла.",
|
||||
"errorParseHint": "Пожалуйста, удостоверьтесь что файл не повреждён и использует кодировку UTF-8.",
|
||||
"errorImport": "Ошибка импорта {count, plural, =1 {# источника} other {# источников}}.",
|
||||
"exist": "Этот источник уже существует.",
|
||||
"opmlFile": "OPML файл",
|
||||
"name": "Название источника",
|
||||
"editName": "Изменить название",
|
||||
"fetchFrequency": "Ограничение частоты обновлений",
|
||||
"unlimited": "Без ограничений",
|
||||
"openTarget": "Метод открытия статей по умолчанию",
|
||||
"delete": "Удалить источник",
|
||||
"add": "Добавить источник",
|
||||
"import": "Импорт",
|
||||
"export": "Экспорт",
|
||||
"rssText": "Полный текст RSS",
|
||||
"loadWebpage": "Загрузить веб-страницу",
|
||||
"inputUrl": "Введите URL",
|
||||
"badIcon": "Недопустимая иконка",
|
||||
"badUrl": "Недопустимый URL",
|
||||
"deleteWarning": "Источник и все сохранённые статьи будут удалены.",
|
||||
"selected": "Выберите источник",
|
||||
"selectedMulti": "Выберите несколько источников"
|
||||
},
|
||||
"groups": {
|
||||
"exist": "Эта группа уже существует.",
|
||||
"type": "Тип",
|
||||
"group": "Группа",
|
||||
"source": "Источник",
|
||||
"capacity": "Ёмкость",
|
||||
"exitGroup": "Назад к группам",
|
||||
"deleteSource": "Удалить из группы",
|
||||
"sourceHint": "Перетаскивайте источники для изменения порядка.",
|
||||
"create": "Создать группу",
|
||||
"selectedGroup": "Выбранная группа",
|
||||
"selectedSource": "Выбранный источник",
|
||||
"enterName": "Введите название",
|
||||
"editName": "Изменить название",
|
||||
"deleteGroup": "Удалить группу",
|
||||
"chooseGroup": "Выбрать группу",
|
||||
"addToGroup": "Добавить в …",
|
||||
"groupHint": "Сделайте двойной щелчок по группе для редактирования источников. Перетаскивайте для изменения порядка."
|
||||
},
|
||||
"rules": {
|
||||
"intro": "Автоматически отмечать статьи или отправлять уведомления с помощью регулярных выражений.",
|
||||
"help": "Узнать больше",
|
||||
"source": "Источник",
|
||||
"selectSource": "Выбрать источник",
|
||||
"new": "Новое правило",
|
||||
"if": "Если",
|
||||
"then": "То",
|
||||
"title": "Название",
|
||||
"content": "Содержимое",
|
||||
"fullSearch": "Название или содержимое",
|
||||
"creator": "Автор",
|
||||
"match": "совпадает",
|
||||
"notMatch": "не совпадает",
|
||||
"regex": "Регулярное выражение",
|
||||
"badRegex": "Недопустимое регулярное выражение.",
|
||||
"action": "Действия",
|
||||
"selectAction": "Выберите действия",
|
||||
"hint": "Правила применяются по порядку. Перетащите для изменения порядка.",
|
||||
"test": "Проверить правила"
|
||||
},
|
||||
"service": {
|
||||
"intro": "Синхронизация между устройствами с помощью RSS сервисов.",
|
||||
"select": "Выберите сервис",
|
||||
"suggest": "Предложить новый сервис",
|
||||
"overwriteWarning": "Локальные источники будут удалены если они существуют в сервисе.",
|
||||
"groupsWarning": "Группы не синхронизируются автоматически через сервис.",
|
||||
"rateLimitWarning": "Чтобы избежать ограничения частоты запросов, Вам нужно создать свой ключ API.",
|
||||
"removeAd": "Убрать рекламу",
|
||||
"endpoint": "Endpoint",
|
||||
"username": "Имя пользователя",
|
||||
"password": "Пароль",
|
||||
"unchanged": "Без изменений",
|
||||
"fetchLimit": "Ограничение синхронизации",
|
||||
"fetchLimitNum": "{count, plural, =1 {# последняя статья} other {# последних статей}}",
|
||||
"importGroups": "Импортировать группы",
|
||||
"failure": "Нет подключения к сервису",
|
||||
"failureHint": "Please check the service configuration or network status.",
|
||||
"fetchUnlimited": "Без ограничений (не рекомендуется)",
|
||||
"exportToLite": "Экспорт в Fluent Reader Lite"
|
||||
},
|
||||
"app": {
|
||||
"cleanup": "Очистка",
|
||||
"cache": "Очистить кэш",
|
||||
"cacheSize": "Закэшировано {size} данных",
|
||||
"deleteChoices": "Удалить статьи старше … дней",
|
||||
"confirmDelete": "Удалить",
|
||||
"daysAgo": "{days, plural, =1 {# дня} other {# дней}} назад",
|
||||
"deleteAll": "Удалить все статьи",
|
||||
"calculatingSize": "Вычисление размера…",
|
||||
"itemSize": "Статьями занято примерно {size} пространства локального хранилища",
|
||||
"confirmImport": "Вы действительно хотите импортировать данные из файла резервной копии? Все текущие данные будут удалены.",
|
||||
"data": "Данные приложения",
|
||||
"backup": "Резервная копия",
|
||||
"restore": "Восстановление",
|
||||
"frData": "Данные Fluent Reader",
|
||||
"language": "Язык интерфейса",
|
||||
"theme": "Тема",
|
||||
"lightTheme": "Светлая",
|
||||
"darkTheme": "Тёмная",
|
||||
"enableProxy": "Включить прокси",
|
||||
"badUrl": "Недопустимый URL",
|
||||
"pac": "PAC Адрес",
|
||||
"setPac": "Установить PAC",
|
||||
"pacHint": "Для Socks прокси рекомендуется, чтобы PAC возвращал \"SOCKS5\" для DNS на стороне прокси. Выключение прокси требует перезапуска.",
|
||||
"fetchInterval": "Интервал автоматического обновления",
|
||||
"never": "Никогда"
|
||||
}
|
||||
}
|
|
@ -32,7 +32,7 @@ import {
|
|||
selectAllArticles,
|
||||
showItemFromId,
|
||||
} from "./page"
|
||||
import { getCurrentLocale } from "../settings"
|
||||
import { getCurrentLocale, setThemeDefaultFont } from "../settings"
|
||||
import locales from "../i18n/_locales"
|
||||
import { SYNC_SERVICE, ServiceActionTypes } from "./service"
|
||||
|
||||
|
@ -369,10 +369,14 @@ export interface InitIntlAction {
|
|||
type: typeof INIT_INTL
|
||||
locale: string
|
||||
}
|
||||
export const initIntlDone = (locale: string): InitIntlAction => ({
|
||||
type: INIT_INTL,
|
||||
locale: locale,
|
||||
})
|
||||
export const initIntlDone = (locale: string): InitIntlAction => {
|
||||
document.documentElement.lang = locale
|
||||
setThemeDefaultFont(locale)
|
||||
return {
|
||||
type: INIT_INTL,
|
||||
locale: locale,
|
||||
}
|
||||
}
|
||||
|
||||
export function initIntl(): AppThunk<Promise<void>> {
|
||||
return dispatch => {
|
||||
|
|
|
@ -5,13 +5,12 @@ import { ThemeSettings } from "../schema-types"
|
|||
import intl from "react-intl-universal"
|
||||
import { SourceTextDirection } from "./models/source"
|
||||
|
||||
const lightTheme: IPartialTheme = {
|
||||
let lightTheme: IPartialTheme = {
|
||||
defaultFontStyle: {
|
||||
fontFamily:
|
||||
'"Segoe UI", "Source Han Sans SC Regular", "Microsoft YaHei", sans-serif',
|
||||
fontFamily: '"Segoe UI", "Source Han Sans Regular", sans-serif',
|
||||
},
|
||||
}
|
||||
const darkTheme: IPartialTheme = {
|
||||
let darkTheme: IPartialTheme = {
|
||||
...lightTheme,
|
||||
palette: {
|
||||
neutralLighterAlt: "#282828",
|
||||
|
@ -41,6 +40,32 @@ const darkTheme: IPartialTheme = {
|
|||
},
|
||||
}
|
||||
|
||||
export function setThemeDefaultFont(locale: string) {
|
||||
switch (locale) {
|
||||
case "zh-CN":
|
||||
lightTheme.defaultFontStyle.fontFamily =
|
||||
'"Segoe UI", "Source Han Sans SC Regular", "Microsoft YaHei", sans-serif'
|
||||
break
|
||||
case "zh-TW":
|
||||
lightTheme.defaultFontStyle.fontFamily =
|
||||
'"Segoe UI", "Source Han Sans TC Regular", "Microsoft JhengHei", sans-serif'
|
||||
break
|
||||
case "ja":
|
||||
lightTheme.defaultFontStyle.fontFamily =
|
||||
'"Segoe UI", "Source Han Sans JP Regular", "Yu Gothic UI", sans-serif'
|
||||
break
|
||||
case "ko":
|
||||
lightTheme.defaultFontStyle.fontFamily =
|
||||
'"Segoe UI", "Source Han Sans KR Regular", "Malgun Gothic", sans-serif'
|
||||
break
|
||||
default:
|
||||
lightTheme.defaultFontStyle.fontFamily =
|
||||
'"Segoe UI", "Source Han Sans Regular", sans-serif'
|
||||
}
|
||||
darkTheme.defaultFontStyle.fontFamily =
|
||||
lightTheme.defaultFontStyle.fontFamily
|
||||
applyThemeSettings()
|
||||
}
|
||||
export function setThemeSettings(theme: ThemeSettings) {
|
||||
window.settings.setThemeSettings(theme)
|
||||
applyThemeSettings()
|
||||
|
|
Loading…
Reference in New Issue