mirror of
https://github.com/KoalaSat/nostros.git
synced 2024-09-29 06:30:47 +00:00
Better Home
This commit is contained in:
parent
7b3bf3e021
commit
4b0d1e3d06
@ -80,22 +80,22 @@ public class Event {
|
||||
|
||||
protected String getReplyEventId() {
|
||||
JSONArray eTags = filterTags("e");
|
||||
String mainEventId = null;
|
||||
String replyEventId = null;
|
||||
try {
|
||||
for (int i = 0; i < eTags.length(); ++i) {
|
||||
JSONArray tag = eTags.getJSONArray(i);
|
||||
if (tag.length() > 3 && tag.getString(3).equals("reply")) {
|
||||
mainEventId = tag.getString(1);
|
||||
replyEventId = tag.getString(1);
|
||||
}
|
||||
}
|
||||
if (mainEventId == null && eTags.length() > 0) {
|
||||
mainEventId = eTags.getJSONArray(eTags.length() - 1).getString(1);
|
||||
if (replyEventId == null && eTags.length() > 0) {
|
||||
replyEventId = eTags.getJSONArray(eTags.length() - 1).getString(1);
|
||||
}
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return mainEventId;
|
||||
return replyEventId;
|
||||
}
|
||||
|
||||
protected String saveFollower(String pubKey) {
|
||||
|
@ -77,14 +77,16 @@ public class DatabaseModule {
|
||||
String query = "SELECT url FROM nostros_relays;";
|
||||
@SuppressLint("Recycle") Cursor cursor = database.rawQuery(query, new String[] {});
|
||||
if (cursor.getCount() > 0) {
|
||||
for (int i = 1; i < cursor.getCount(); i++) {
|
||||
cursor.moveToFirst();
|
||||
while (!cursor.isAfterLast()) {
|
||||
try {
|
||||
String relayUrl = cursor.getString(i);
|
||||
String relayUrl = cursor.getString(0);
|
||||
Relay relay = new Relay(relayUrl, this, reactContext);
|
||||
relayList.add(relay);
|
||||
} catch (IOException e) {
|
||||
Log.d("WebSocket", e.toString());
|
||||
}
|
||||
cursor.moveToNext();
|
||||
}
|
||||
}
|
||||
return relayList;
|
||||
|
@ -25,7 +25,6 @@ import {
|
||||
} from '../../Functions/RelayFunctions/DirectMessages'
|
||||
import Avatar from '../Avatar'
|
||||
import Icon from 'react-native-vector-icons/FontAwesome5'
|
||||
import { decrypt } from 'nostr-tools/nip04'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { username } from '../../Functions/RelayFunctions/Users'
|
||||
|
||||
@ -100,16 +99,6 @@ export const DirectMessagesPage: React.FC = () => {
|
||||
|
||||
const otherPubKey = getOtherPubKey(message, publicKey)
|
||||
const user: User = users?.find((user) => user.id === otherPubKey) ?? { id: otherPubKey }
|
||||
let decryptedContent = ''
|
||||
|
||||
try {
|
||||
decryptedContent = decrypt(privateKey, otherPubKey, message.content ?? '')
|
||||
} catch {
|
||||
return <View key={message.id}></View>
|
||||
}
|
||||
|
||||
const content =
|
||||
decryptedContent.length > 35 ? `${decryptedContent.substring(0, 35)}...` : decryptedContent
|
||||
|
||||
return (
|
||||
<Card
|
||||
@ -121,8 +110,7 @@ export const DirectMessagesPage: React.FC = () => {
|
||||
<Avatar name={user.name} src={user.picture} pubKey={user.id} />
|
||||
</Layout>
|
||||
<Layout style={styles.content} level='2'>
|
||||
<Text>{username(user)}</Text>
|
||||
<Text appearance='hint'>{content}</Text>
|
||||
<Text category='h6'>{username(user)}</Text>
|
||||
</Layout>
|
||||
<Layout style={styles.layout}>
|
||||
{!message.read ? (
|
||||
@ -155,6 +143,7 @@ export const DirectMessagesPage: React.FC = () => {
|
||||
content: {
|
||||
flex: 6,
|
||||
backgroundColor: 'transparent',
|
||||
justifyContent: 'center',
|
||||
},
|
||||
actionContainer: {
|
||||
marginTop: 30,
|
||||
|
@ -1,15 +1,15 @@
|
||||
import { Card, Layout, Spinner, useTheme } from '@ui-kitten/components'
|
||||
import { Card, Layout, Text, useTheme } from '@ui-kitten/components'
|
||||
import React, { useContext, useEffect, useState } from 'react'
|
||||
import { t } from 'i18next'
|
||||
import {
|
||||
NativeScrollEvent,
|
||||
NativeSyntheticEvent,
|
||||
ScrollView,
|
||||
StyleSheet,
|
||||
TouchableOpacity,
|
||||
View,
|
||||
} from 'react-native'
|
||||
import { AppContext } from '../../Contexts/AppContext'
|
||||
import { getNotes, Note } from '../../Functions/DatabaseFunctions/Notes'
|
||||
import { getMainNotes, Note } from '../../Functions/DatabaseFunctions/Notes'
|
||||
import NoteCard from '../NoteCard'
|
||||
import Icon from 'react-native-vector-icons/FontAwesome5'
|
||||
import { RelayPoolContext } from '../../Contexts/RelayPoolContext'
|
||||
@ -17,7 +17,6 @@ import { EventKind } from '../../lib/nostr/Events'
|
||||
import { getReplyEventId } from '../../Functions/RelayFunctions/Events'
|
||||
import { getUsers, User } from '../../Functions/DatabaseFunctions/Users'
|
||||
import { handleInfinityScroll } from '../../Functions/NativeFunctions'
|
||||
import Loading from '../Loading'
|
||||
import { RelayFilters } from '../../lib/nostr/RelayPool/intex'
|
||||
|
||||
export const HomePage: React.FC = () => {
|
||||
@ -37,33 +36,40 @@ export const HomePage: React.FC = () => {
|
||||
}
|
||||
}
|
||||
|
||||
const subscribeNotes: (users: User[], past?: boolean) => void = (users, past) => {
|
||||
const subscribeNotes: (users: User[], past?: boolean) => void = async (users, past) => {
|
||||
if (!database || !publicKey || users.length === 0) return
|
||||
|
||||
const lastNotes: Note[] = await getMainNotes(database, publicKey, 1)
|
||||
const lastNote: Note = lastNotes[0]
|
||||
|
||||
const message: RelayFilters = {
|
||||
kinds: [EventKind.textNote, EventKind.recommendServer],
|
||||
authors: users.map((user) => user.id),
|
||||
limit: pageSize,
|
||||
}
|
||||
|
||||
if (lastNote) {
|
||||
message.since = lastNote.created_at
|
||||
} else {
|
||||
message.limit = pageSize
|
||||
}
|
||||
|
||||
relayPool?.subscribe('main-channel', message)
|
||||
}
|
||||
|
||||
const loadNotes: () => void = () => {
|
||||
if (database && publicKey) {
|
||||
getNotes(database, { contacts: true, includeIds: [publicKey], limit: pageSize }).then(
|
||||
(notes) => {
|
||||
setNotes(notes)
|
||||
const missingDataNotes = notes
|
||||
.filter((note) => !note.picture || note.picture === '')
|
||||
.map((note) => note.pubkey)
|
||||
if (missingDataNotes.length > 0) {
|
||||
relayPool?.subscribe('main-channel', {
|
||||
kinds: [EventKind.meta],
|
||||
authors: missingDataNotes,
|
||||
})
|
||||
}
|
||||
},
|
||||
)
|
||||
getMainNotes(database, publicKey, pageSize).then((notes) => {
|
||||
setNotes(notes)
|
||||
const missingDataNotes = notes
|
||||
.filter((note) => !note.picture || note.picture === '')
|
||||
.map((note) => note.pubkey)
|
||||
if (missingDataNotes.length > 0) {
|
||||
relayPool?.subscribe('main-channel', {
|
||||
kinds: [EventKind.meta],
|
||||
authors: missingDataNotes,
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@ -100,7 +106,7 @@ export const HomePage: React.FC = () => {
|
||||
const itemCard: (note: Note) => JSX.Element = (note) => {
|
||||
return (
|
||||
<Card onPress={() => onPress(note)} key={note.id ?? ''}>
|
||||
<NoteCard note={note} />
|
||||
<NoteCard note={note} onlyContactsReplies={true} showReplies={true} />
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
@ -119,13 +125,10 @@ export const HomePage: React.FC = () => {
|
||||
width: 32,
|
||||
height: 32,
|
||||
},
|
||||
loadingBottom: {
|
||||
flex: 1,
|
||||
flexDirection: 'row',
|
||||
empty: {
|
||||
height: 64,
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
flexWrap: 'wrap',
|
||||
padding: 12,
|
||||
},
|
||||
})
|
||||
|
||||
@ -135,12 +138,11 @@ export const HomePage: React.FC = () => {
|
||||
{notes && notes.length > 0 ? (
|
||||
<ScrollView onScroll={onScroll} horizontal={false}>
|
||||
{notes.map((note) => itemCard(note))}
|
||||
<View style={styles.loadingBottom}>
|
||||
<Spinner size='tiny' />
|
||||
</View>
|
||||
</ScrollView>
|
||||
) : (
|
||||
<Loading />
|
||||
<Layout style={styles.empty} level='3'>
|
||||
<Text>{t('homePage.noContacts')}</Text>
|
||||
</Layout>
|
||||
)}
|
||||
</Layout>
|
||||
{privateKey && (
|
||||
|
@ -1,16 +1,28 @@
|
||||
import React from 'react'
|
||||
import { Layout, Text } from '@ui-kitten/components'
|
||||
import { StyleSheet } from 'react-native'
|
||||
import { Layout, Text, useTheme } from '@ui-kitten/components'
|
||||
import { Linking, StyleSheet, TouchableOpacity } from 'react-native'
|
||||
import Loading from '../Loading'
|
||||
import Logger from './Logger'
|
||||
import Icon from 'react-native-vector-icons/FontAwesome5'
|
||||
|
||||
export const LandingPage: React.FC = () => {
|
||||
const theme = useTheme()
|
||||
|
||||
const onPressQuestion: () => void = () => {
|
||||
Linking.openURL('https://usenostr.org')
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
tab: {
|
||||
height: '100%',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
},
|
||||
info: {
|
||||
alignItems: 'flex-end',
|
||||
padding: 12,
|
||||
paddingBottom: -12,
|
||||
},
|
||||
svg: {
|
||||
height: 340,
|
||||
width: 340,
|
||||
@ -24,13 +36,20 @@ export const LandingPage: React.FC = () => {
|
||||
})
|
||||
|
||||
return (
|
||||
<Layout style={styles.tab}>
|
||||
<Layout style={styles.svg}>
|
||||
<Loading />
|
||||
<>
|
||||
<Layout style={styles.info}>
|
||||
<TouchableOpacity onPress={onPressQuestion}>
|
||||
<Icon name='question' size={24} color={theme['text-basic-color']} />
|
||||
</TouchableOpacity>
|
||||
</Layout>
|
||||
<Text style={styles.title}>NOSTROS</Text>
|
||||
<Logger />
|
||||
</Layout>
|
||||
<Layout style={styles.tab}>
|
||||
<Layout style={styles.svg}>
|
||||
<Loading />
|
||||
</Layout>
|
||||
<Text style={styles.title}>NOSTROS</Text>
|
||||
<Logger />
|
||||
</Layout>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
import React, { useContext, useEffect, useState } from 'react'
|
||||
import { Button, Layout, Text, useTheme } from '@ui-kitten/components'
|
||||
import { Note } from '../../Functions/DatabaseFunctions/Notes'
|
||||
import { Button, Divider, Layout, Text, useTheme } from '@ui-kitten/components'
|
||||
import { getNotes, Note } from '../../Functions/DatabaseFunctions/Notes'
|
||||
import { StyleSheet, TouchableOpacity } from 'react-native'
|
||||
import Markdown from 'react-native-markdown-display'
|
||||
import { EventKind } from '../../lib/nostr/Events'
|
||||
@ -9,32 +9,56 @@ import { RelayPoolContext } from '../../Contexts/RelayPoolContext'
|
||||
import { AppContext } from '../../Contexts/AppContext'
|
||||
import { showMessage } from 'react-native-flash-message'
|
||||
import { t } from 'i18next'
|
||||
import { getReplyEventId } from '../../Functions/RelayFunctions/Events'
|
||||
import { getDirectReplies, getReplyEventId } from '../../Functions/RelayFunctions/Events'
|
||||
import moment from 'moment'
|
||||
import { populateRelay } from '../../Functions/RelayFunctions'
|
||||
import Avatar from '../Avatar'
|
||||
import { markdownIt, markdownStyle } from '../../Constants/AppConstants'
|
||||
import { searchRelays } from '../../Functions/DatabaseFunctions/Relays'
|
||||
import { RelayFilters } from '../../lib/nostr/RelayPool/intex'
|
||||
|
||||
interface NoteCardProps {
|
||||
note: Note
|
||||
showReplies?: boolean
|
||||
onlyContactsReplies?: boolean
|
||||
}
|
||||
|
||||
export const NoteCard: React.FC<NoteCardProps> = ({ note }) => {
|
||||
export const NoteCard: React.FC<NoteCardProps> = ({
|
||||
note,
|
||||
showReplies = false,
|
||||
onlyContactsReplies = false,
|
||||
}) => {
|
||||
const theme = useTheme()
|
||||
const { relayPool, publicKey } = useContext(RelayPoolContext)
|
||||
const { database, goToPage } = useContext(AppContext)
|
||||
const [relayAdded, setRelayAdded] = useState<boolean>(false)
|
||||
const [replies, setReplies] = useState<Note[]>([])
|
||||
|
||||
useEffect(() => {
|
||||
if (database) {
|
||||
if (database && note) {
|
||||
searchRelays(note.content, database).then((result) => {
|
||||
setRelayAdded(result.length > 0)
|
||||
})
|
||||
if (showReplies) {
|
||||
getNotes(database, {
|
||||
filters: { reply_event_id: note?.id ?? '' },
|
||||
contacts: onlyContactsReplies,
|
||||
}).then((notes) => {
|
||||
const rootReplies = getDirectReplies(note, notes) as Note[]
|
||||
setReplies(rootReplies)
|
||||
if (rootReplies.length > 0) {
|
||||
const message: RelayFilters = {
|
||||
kinds: [EventKind.meta],
|
||||
authors: [...rootReplies.map((reply) => reply.pubkey), note.pubkey],
|
||||
}
|
||||
relayPool?.subscribe('main-channel', message)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}, [database])
|
||||
|
||||
const textNote: () => JSX.Element = () => {
|
||||
const textNote: (note: Note) => JSX.Element = (note) => {
|
||||
return (
|
||||
<>
|
||||
<Layout style={styles.profile} level='2'>
|
||||
@ -74,7 +98,7 @@ export const NoteCard: React.FC<NoteCardProps> = ({ note }) => {
|
||||
)
|
||||
}
|
||||
|
||||
const relayNote: () => JSX.Element = () => {
|
||||
const relayNote: (note: Note) => JSX.Element = (note) => {
|
||||
const relayName = note.content.split('wss://')[1]?.split('/')[0]
|
||||
|
||||
const addRelayItem: () => void = () => {
|
||||
@ -123,6 +147,15 @@ export const NoteCard: React.FC<NoteCardProps> = ({ note }) => {
|
||||
layout: {
|
||||
flexDirection: 'row',
|
||||
backgroundColor: 'transparent',
|
||||
paddingBottom: 16,
|
||||
},
|
||||
replies: {
|
||||
flexDirection: 'row',
|
||||
backgroundColor: 'transparent',
|
||||
paddingTop: 16,
|
||||
},
|
||||
divider: {
|
||||
paddingTop: 16,
|
||||
},
|
||||
profile: {
|
||||
flex: 1,
|
||||
@ -168,9 +201,23 @@ export const NoteCard: React.FC<NoteCardProps> = ({ note }) => {
|
||||
|
||||
return (
|
||||
note && (
|
||||
<Layout style={styles.layout} level='2'>
|
||||
{note.kind === EventKind.recommendServer ? relayNote() : textNote()}
|
||||
</Layout>
|
||||
<>
|
||||
<Layout style={styles.layout} level='2'>
|
||||
{note.kind === EventKind.recommendServer ? relayNote(note) : textNote(note)}
|
||||
</Layout>
|
||||
{replies.length > 0 ? (
|
||||
<>
|
||||
<Divider />
|
||||
{replies.map((reply) => (
|
||||
<Layout style={styles.replies} level='3' key={reply.id}>
|
||||
{textNote(reply)}
|
||||
</Layout>
|
||||
))}
|
||||
</>
|
||||
) : (
|
||||
<></>
|
||||
)}
|
||||
</>
|
||||
)
|
||||
)
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { Button, Card, Layout, Spinner, TopNavigation, useTheme } from '@ui-kitten/components'
|
||||
import { Button, Card, Layout, TopNavigation, useTheme } from '@ui-kitten/components'
|
||||
import React, { useContext, useEffect, useState } from 'react'
|
||||
import { AppContext } from '../../Contexts/AppContext'
|
||||
import { getNotes, Note } from '../../Functions/DatabaseFunctions/Notes'
|
||||
@ -6,7 +6,7 @@ import { RelayPoolContext } from '../../Contexts/RelayPoolContext'
|
||||
import Icon from 'react-native-vector-icons/FontAwesome5'
|
||||
import NoteCard from '../NoteCard'
|
||||
import { EventKind } from '../../lib/nostr/Events'
|
||||
import { Clipboard, ScrollView, StyleSheet, Text, TouchableOpacity, View } from 'react-native'
|
||||
import { Clipboard, ScrollView, StyleSheet, Text, TouchableOpacity } from 'react-native'
|
||||
import Loading from '../Loading'
|
||||
import { getDirectReplies, getReplyEventId } from '../../Functions/RelayFunctions/Events'
|
||||
import { RelayFilters } from '../../lib/nostr/RelayPool/intex'
|
||||
@ -155,14 +155,6 @@ export const NotePage: React.FC = () => {
|
||||
loading: {
|
||||
maxHeight: 160,
|
||||
},
|
||||
loadingBottom: {
|
||||
flex: 1,
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
flexWrap: 'wrap',
|
||||
padding: 12,
|
||||
},
|
||||
})
|
||||
|
||||
return (
|
||||
@ -181,9 +173,6 @@ export const NotePage: React.FC = () => {
|
||||
{note ? (
|
||||
<ScrollView horizontal={false}>
|
||||
{[note, ...(replies ?? [])].map((note) => itemCard(note))}
|
||||
<View style={styles.loadingBottom}>
|
||||
<Spinner size='tiny' />
|
||||
</View>
|
||||
</ScrollView>
|
||||
) : (
|
||||
<Loading style={styles.loading} />
|
||||
|
@ -8,7 +8,6 @@ import {
|
||||
ScrollView,
|
||||
StyleSheet,
|
||||
TouchableOpacity,
|
||||
View,
|
||||
} from 'react-native'
|
||||
import { AppContext } from '../../Contexts/AppContext'
|
||||
import { getNotes, Note } from '../../Functions/DatabaseFunctions/Notes'
|
||||
@ -231,20 +230,12 @@ export const ProfilePage: React.FC = () => {
|
||||
marginTop: 16,
|
||||
flexDirection: 'row',
|
||||
},
|
||||
loadingBottom: {
|
||||
flex: 1,
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
flexWrap: 'wrap',
|
||||
padding: 12,
|
||||
},
|
||||
})
|
||||
|
||||
const itemCard: (note: Note) => JSX.Element = (note) => {
|
||||
return (
|
||||
<Card onPress={() => onPressNote(note)} key={note.id ?? ''}>
|
||||
<NoteCard note={note} />
|
||||
<NoteCard note={note} onlyContactsReplies={true} />
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
@ -315,9 +306,6 @@ export const ProfilePage: React.FC = () => {
|
||||
refreshControl={<RefreshControl refreshing={refreshing} onRefresh={onRefresh} />}
|
||||
>
|
||||
{notes.map((note) => itemCard(note))}
|
||||
<View style={styles.loadingBottom}>
|
||||
<Spinner size='tiny' />
|
||||
</View>
|
||||
</ScrollView>
|
||||
) : (
|
||||
<Loading />
|
||||
|
@ -43,7 +43,7 @@ export const RelaysPage: React.FC = () => {
|
||||
)
|
||||
|
||||
const addRelayItem: (url: string) => void = async (url) => {
|
||||
if (relayPool && database && publicKey && (relays?.length ?? 0) < 2) {
|
||||
if (relayPool && database && publicKey) {
|
||||
setLoading(true)
|
||||
relayPool.add(url, () => {
|
||||
showMessage({
|
||||
@ -81,7 +81,7 @@ export const RelaysPage: React.FC = () => {
|
||||
) : (
|
||||
<Button
|
||||
status='success'
|
||||
disabled={loading || (relays?.length ?? 0) > 0}
|
||||
disabled={loading}
|
||||
onPress={() => addRelayItem(relay.url)}
|
||||
accessoryLeft={<Icon name='plus' size={16} color={theme['text-basic-color']} solid />}
|
||||
/>
|
||||
|
@ -12,6 +12,29 @@ const databaseToEntity: (object: any) => Note = (object) => {
|
||||
return object as Note
|
||||
}
|
||||
|
||||
export const getMainNotes: (
|
||||
db: QuickSQLiteConnection,
|
||||
pubKey: string,
|
||||
limit: number,
|
||||
) => Promise<Note[]> = async (db, pubKey, limit) => {
|
||||
const notesQuery = `
|
||||
SELECT
|
||||
nostros_notes.*, nostros_users.name, nostros_users.picture, nostros_users.contact FROM nostros_notes
|
||||
LEFT JOIN
|
||||
nostros_users ON nostros_users.id = nostros_notes.pubkey
|
||||
WHERE (nostros_users.contact = 1 OR nostros_users.id = '${pubKey}')
|
||||
AND nostros_notes.main_event_id IS NULL
|
||||
ORDER BY created_at DESC
|
||||
LIMIT ${limit}
|
||||
`
|
||||
|
||||
const resultSet = await db.execute(notesQuery)
|
||||
const items: object[] = getItems(resultSet)
|
||||
const notes: Note[] = items.map((object) => databaseToEntity(object))
|
||||
|
||||
return notes
|
||||
}
|
||||
|
||||
export const getNotes: (
|
||||
db: QuickSQLiteConnection,
|
||||
options: {
|
||||
|
@ -15,7 +15,8 @@
|
||||
},
|
||||
"homePage": {
|
||||
"search": "Search",
|
||||
"send": "Send"
|
||||
"send": "Send",
|
||||
"noContacts": "You have no contacts yet"
|
||||
},
|
||||
"logger": {
|
||||
"randomKeyGenerator": {
|
||||
|
72
frontend/Locales/es.json
Normal file
72
frontend/Locales/es.json
Normal file
@ -0,0 +1,72 @@
|
||||
{
|
||||
"common": {
|
||||
"landing": {
|
||||
"connect": "Conectar",
|
||||
"connecting": "Conectando",
|
||||
"loadingContacts": "Cargando Contactos",
|
||||
"loadingEvents": "Cargando Eventos",
|
||||
"ready": "Listo",
|
||||
"privateKey": "Clave Privada",
|
||||
"publicKey": "Clave Pública"
|
||||
},
|
||||
"navigationBar": {
|
||||
"home": "Home",
|
||||
"profile": "Perfil"
|
||||
},
|
||||
"homePage": {
|
||||
"search": "Buscar",
|
||||
"send": "Enviar",
|
||||
"noContacts": "Aún no tienes contactos"
|
||||
},
|
||||
"logger": {
|
||||
"randomKeyGenerator": {
|
||||
"message": "Tu clave privada ha sido copiada al porta-papeles",
|
||||
"description": "Guardala en un ligar seguro para recuperar tu usuario"
|
||||
}
|
||||
},
|
||||
"profilePage": {
|
||||
"search": "Burcar",
|
||||
"send": "Enviar",
|
||||
"profileNotCreated": "Perfil aún no creado"
|
||||
},
|
||||
"relaysPage": {
|
||||
"title": "Relays"
|
||||
},
|
||||
"notePage": {
|
||||
"reply": "Responder"
|
||||
},
|
||||
"configPage": {
|
||||
"title": "Configuraciónn",
|
||||
"logout": "Borrar Claves",
|
||||
"relays": "Relays",
|
||||
"publicKey": "Clave Pública",
|
||||
"privateKey": "Clave Privada"
|
||||
},
|
||||
"direcMessagesPage": {
|
||||
"sendMessage": {
|
||||
"placeholder": "Clave Pública",
|
||||
"send": "Abrir Conversación",
|
||||
"contacts": "Contactos"
|
||||
}
|
||||
},
|
||||
"contactsPage": {
|
||||
"following": "Siguiendo",
|
||||
"followers": "Seguidores",
|
||||
"add": "Añadir Usuario",
|
||||
"addContact": {
|
||||
"placeholder": "Clave Pública",
|
||||
"add": "Añadir Usuario"
|
||||
}
|
||||
},
|
||||
"sendPage": {
|
||||
"title": "Enviar Nota",
|
||||
"placeholder": "Di algo al mundo...",
|
||||
"send": "Enviar",
|
||||
"reply": "Enviar respuesta"
|
||||
},
|
||||
"alerts": {
|
||||
"relayAdded": "Relay Agregado",
|
||||
"relayRemoved": "Relay Eliminado"
|
||||
}
|
||||
}
|
||||
}
|
72
frontend/Locales/ru.json
Normal file
72
frontend/Locales/ru.json
Normal file
@ -0,0 +1,72 @@
|
||||
{
|
||||
"common": {
|
||||
"landing": {
|
||||
"connect": "Подключить",
|
||||
"connecting": "Подключение",
|
||||
"loadingContacts": "Загрузка контактов",
|
||||
"loadingEvents": "Загрузка событий",
|
||||
"ready": "Готова",
|
||||
"privateKey": "Приватный ключ",
|
||||
"publicKey": "Публичный ключ"
|
||||
},
|
||||
"navigationBar": {
|
||||
"home": "Главная страницы",
|
||||
"profile": "Профиль"
|
||||
},
|
||||
"homePage": {
|
||||
"search": "Поиск",
|
||||
"send": "Отправить",
|
||||
"noContacts": "У Вас пока нет контактов"
|
||||
},
|
||||
"logger": {
|
||||
"randomKeyGenerator": {
|
||||
"message": "Ваш приватный ключ был скопирован",
|
||||
"description": "Сохраните его в надеждном месте, чтобы восстановить доступ к акканунту"
|
||||
}
|
||||
},
|
||||
"profilePage": {
|
||||
"search": "Поиск",
|
||||
"send": "Отправить",
|
||||
"profileNotCreated": "Профиль не создан"
|
||||
},
|
||||
"relaysPage": {
|
||||
"title": "Все реле"
|
||||
},
|
||||
"notePage": {
|
||||
"reply": "Ответить"
|
||||
},
|
||||
"configPage": {
|
||||
"title": "Настройки",
|
||||
"logout": "Удалить ключи",
|
||||
"relays": "Реле",
|
||||
"publicKey": "Публичный ключ",
|
||||
"privateKey": "Приватный ключ"
|
||||
},
|
||||
"direcMessagesPage": {
|
||||
"sendMessage": {
|
||||
"placeholder": "Публичный ключ",
|
||||
"send": "Открыть диалог",
|
||||
"contacts": "Контакты"
|
||||
}
|
||||
},
|
||||
"contactsPage": {
|
||||
"following": "Подписки",
|
||||
"followers": "Подписчики",
|
||||
"add": "Добавить контакт",
|
||||
"addContact": {
|
||||
"placeholder": "Публичный ключ",
|
||||
"add": "Добавить контакт"
|
||||
}
|
||||
},
|
||||
"sendPage": {
|
||||
"title": "Опубликовать заметку",
|
||||
"placeholder": "Поделитесь чем-нибудь с миром",
|
||||
"send": "Опубликовать",
|
||||
"reply": "Ответить"
|
||||
},
|
||||
"alerts": {
|
||||
"relayAdded": "Реле добавлено",
|
||||
"relayRemoved": "Реле удалено"
|
||||
}
|
||||
}
|
||||
}
|
@ -1,12 +1,16 @@
|
||||
import i18n from 'i18next'
|
||||
import { initReactI18next } from 'react-i18next'
|
||||
import en from './Locales/en.json'
|
||||
import es from './Locales/es.json'
|
||||
import ru from './Locales/ru.json'
|
||||
|
||||
i18n.use(initReactI18next).init({
|
||||
compatibilityJSON: 'v3',
|
||||
fallbackLng: 'en',
|
||||
resources: {
|
||||
en,
|
||||
es,
|
||||
ru,
|
||||
},
|
||||
ns: ['common'],
|
||||
defaultNS: 'common',
|
||||
|
Loading…
Reference in New Issue
Block a user