mirror of
https://github.com/LemmyNet/lemmy
synced 2024-11-10 06:54:12 +00:00
parent
4c7da003a2
commit
f0808a1116
20 changed files with 107 additions and 17 deletions
18
README.md
vendored
18
README.md
vendored
|
@ -247,15 +247,15 @@ If you'd like to add translations, take a look a look at the [English translatio
|
|||
|
||||
lang | done | missing
|
||||
--- | --- | ---
|
||||
de | 79% | cross_posts,cross_post,users,number_of_communities,preview,upload_image,formatting_help,view_source,sticky,unsticky,archive_link,settings,stickied,delete_account,delete_account_confirm,banned,creator,number_online,subscribed,replies,mentions,forgot_password,reset_password_mail_sent,password_change,new_password,no_email_setup,expires,recent_comments,nsfw,show_nsfw,theme,crypto,monero,joined,by,to,transfer_community,transfer_site,are_you_sure,yes,no
|
||||
eo | 87% | number_of_communities,preview,upload_image,formatting_help,view_source,sticky,unsticky,archive_link,stickied,delete_account,delete_account_confirm,banned,creator,number_online,replies,mentions,forgot_password,reset_password_mail_sent,password_change,new_password,no_email_setup,theme,are_you_sure,yes,no
|
||||
es | 96% | archive_link,replies,mentions,forgot_password,reset_password_mail_sent,password_change,new_password,no_email_setup
|
||||
fr | 96% | archive_link,replies,mentions,forgot_password,reset_password_mail_sent,password_change,new_password,no_email_setup
|
||||
it | 97% | archive_link,forgot_password,reset_password_mail_sent,password_change,new_password,no_email_setup
|
||||
nl | 89% | preview,upload_image,formatting_help,view_source,sticky,unsticky,archive_link,stickied,delete_account,delete_account_confirm,banned,creator,number_online,replies,mentions,forgot_password,reset_password_mail_sent,password_change,new_password,no_email_setup,theme
|
||||
ru | 83% | cross_posts,cross_post,number_of_communities,preview,upload_image,formatting_help,view_source,sticky,unsticky,archive_link,stickied,delete_account,delete_account_confirm,banned,creator,number_online,replies,mentions,forgot_password,reset_password_mail_sent,password_change,new_password,no_email_setup,recent_comments,theme,monero,by,to,transfer_community,transfer_site,are_you_sure,yes,no
|
||||
sv | 96% | archive_link,replies,mentions,forgot_password,reset_password_mail_sent,password_change,new_password,no_email_setup
|
||||
zh | 81% | cross_posts,cross_post,users,number_of_communities,preview,upload_image,formatting_help,view_source,sticky,unsticky,archive_link,settings,stickied,delete_account,delete_account_confirm,banned,creator,number_online,replies,mentions,forgot_password,reset_password_mail_sent,password_change,new_password,no_email_setup,recent_comments,nsfw,show_nsfw,theme,monero,by,to,transfer_community,transfer_site,are_you_sure,yes,no
|
||||
de | 78% | cross_posts,cross_post,users,number_of_communities,preview,upload_image,formatting_help,view_source,sticky,unsticky,archive_link,settings,stickied,delete_account,delete_account_confirm,banned,creator,number_online,subscribed,replies,mentions,forgot_password,reset_password_mail_sent,password_change,new_password,no_email_setup,expires,language,browser_default,recent_comments,nsfw,show_nsfw,theme,crypto,monero,joined,by,to,transfer_community,transfer_site,are_you_sure,yes,no
|
||||
eo | 86% | number_of_communities,preview,upload_image,formatting_help,view_source,sticky,unsticky,archive_link,stickied,delete_account,delete_account_confirm,banned,creator,number_online,replies,mentions,forgot_password,reset_password_mail_sent,password_change,new_password,no_email_setup,language,browser_default,theme,are_you_sure,yes,no
|
||||
es | 95% | archive_link,replies,mentions,forgot_password,reset_password_mail_sent,password_change,new_password,no_email_setup,language,browser_default
|
||||
fr | 95% | archive_link,replies,mentions,forgot_password,reset_password_mail_sent,password_change,new_password,no_email_setup,language,browser_default
|
||||
it | 96% | archive_link,forgot_password,reset_password_mail_sent,password_change,new_password,no_email_setup,language,browser_default
|
||||
nl | 88% | preview,upload_image,formatting_help,view_source,sticky,unsticky,archive_link,stickied,delete_account,delete_account_confirm,banned,creator,number_online,replies,mentions,forgot_password,reset_password_mail_sent,password_change,new_password,no_email_setup,language,browser_default,theme
|
||||
ru | 82% | cross_posts,cross_post,number_of_communities,preview,upload_image,formatting_help,view_source,sticky,unsticky,archive_link,stickied,delete_account,delete_account_confirm,banned,creator,number_online,replies,mentions,forgot_password,reset_password_mail_sent,password_change,new_password,no_email_setup,language,browser_default,recent_comments,theme,monero,by,to,transfer_community,transfer_site,are_you_sure,yes,no
|
||||
sv | 95% | archive_link,replies,mentions,forgot_password,reset_password_mail_sent,password_change,new_password,no_email_setup,language,browser_default
|
||||
zh | 80% | cross_posts,cross_post,users,number_of_communities,preview,upload_image,formatting_help,view_source,sticky,unsticky,archive_link,settings,stickied,delete_account,delete_account_confirm,banned,creator,number_online,replies,mentions,forgot_password,reset_password_mail_sent,password_change,new_password,no_email_setup,language,browser_default,recent_comments,nsfw,show_nsfw,theme,monero,by,to,transfer_community,transfer_site,are_you_sure,yes,no
|
||||
|
||||
|
||||
If you'd like to update this report, run:
|
||||
|
|
2
install.sh
vendored
2
install.sh
vendored
|
@ -1,7 +1,7 @@
|
|||
#!/bin/sh
|
||||
set -e
|
||||
|
||||
export DATABASE_URL=postgres://rrr:rrr@localhost/rrr
|
||||
export DATABASE_URL=postgres://lemmy:password@localhost:5432/lemmy
|
||||
export JWT_SECRET=changeme
|
||||
export HOSTNAME=rrr
|
||||
|
||||
|
|
1
server/migrations/2019-12-09-060754_add_lang/down.sql
vendored
Normal file
1
server/migrations/2019-12-09-060754_add_lang/down.sql
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
alter table user_ drop column lang;
|
1
server/migrations/2019-12-09-060754_add_lang/up.sql
vendored
Normal file
1
server/migrations/2019-12-09-060754_add_lang/up.sql
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
alter table user_ add column lang varchar(20) default 'browser' not null;
|
|
@ -25,6 +25,7 @@ pub struct SaveUserSettings {
|
|||
theme: String,
|
||||
default_sort_type: i16,
|
||||
default_listing_type: i16,
|
||||
lang: String,
|
||||
auth: String,
|
||||
}
|
||||
|
||||
|
@ -220,6 +221,7 @@ impl Perform<LoginResponse> for Oper<Register> {
|
|||
theme: "darkly".into(),
|
||||
default_sort_type: SortType::Hot as i16,
|
||||
default_listing_type: ListingType::Subscribed as i16,
|
||||
lang: "browser".into(),
|
||||
};
|
||||
|
||||
// Create the user
|
||||
|
@ -313,6 +315,7 @@ impl Perform<LoginResponse> for Oper<SaveUserSettings> {
|
|||
theme: data.theme.to_owned(),
|
||||
default_sort_type: data.default_sort_type,
|
||||
default_listing_type: data.default_listing_type,
|
||||
lang: data.lang.to_owned(),
|
||||
};
|
||||
|
||||
let updated_user = match User_::update(&conn, user_id, &user_form) {
|
||||
|
@ -445,6 +448,7 @@ impl Perform<AddAdminResponse> for Oper<AddAdmin> {
|
|||
theme: read_user.theme,
|
||||
default_sort_type: read_user.default_sort_type,
|
||||
default_listing_type: read_user.default_listing_type,
|
||||
lang: read_user.lang,
|
||||
};
|
||||
|
||||
match User_::update(&conn, data.user_id, &user_form) {
|
||||
|
@ -506,6 +510,7 @@ impl Perform<BanUserResponse> for Oper<BanUser> {
|
|||
theme: read_user.theme,
|
||||
default_sort_type: read_user.default_sort_type,
|
||||
default_listing_type: read_user.default_listing_type,
|
||||
lang: read_user.lang,
|
||||
};
|
||||
|
||||
match User_::update(&conn, data.user_id, &user_form) {
|
||||
|
@ -842,6 +847,7 @@ impl Perform<LoginResponse> for Oper<PasswordChange> {
|
|||
theme: read_user.theme,
|
||||
default_sort_type: read_user.default_sort_type,
|
||||
default_listing_type: read_user.default_listing_type,
|
||||
lang: read_user.lang,
|
||||
};
|
||||
|
||||
let updated_user = match User_::update_password(&conn, user_id, &user_form) {
|
||||
|
|
|
@ -76,6 +76,7 @@ mod tests {
|
|||
theme: "darkly".into(),
|
||||
default_sort_type: SortType::Hot as i16,
|
||||
default_listing_type: ListingType::Subscribed as i16,
|
||||
lang: "browser".into(),
|
||||
};
|
||||
|
||||
let person = expected_user.person();
|
||||
|
|
|
@ -181,6 +181,7 @@ mod tests {
|
|||
theme: "darkly".into(),
|
||||
default_sort_type: SortType::Hot as i16,
|
||||
default_listing_type: ListingType::Subscribed as i16,
|
||||
lang: "browser".into(),
|
||||
};
|
||||
|
||||
let inserted_user = User_::create(&conn, &new_user).unwrap();
|
||||
|
|
|
@ -415,6 +415,7 @@ mod tests {
|
|||
theme: "darkly".into(),
|
||||
default_sort_type: SortType::Hot as i16,
|
||||
default_listing_type: ListingType::Subscribed as i16,
|
||||
lang: "browser".into(),
|
||||
};
|
||||
|
||||
let inserted_user = User_::create(&conn, &new_user).unwrap();
|
||||
|
|
|
@ -267,6 +267,7 @@ mod tests {
|
|||
theme: "darkly".into(),
|
||||
default_sort_type: SortType::Hot as i16,
|
||||
default_listing_type: ListingType::Subscribed as i16,
|
||||
lang: "browser".into(),
|
||||
};
|
||||
|
||||
let inserted_user = User_::create(&conn, &new_user).unwrap();
|
||||
|
|
|
@ -449,6 +449,7 @@ mod tests {
|
|||
theme: "darkly".into(),
|
||||
default_sort_type: SortType::Hot as i16,
|
||||
default_listing_type: ListingType::Subscribed as i16,
|
||||
lang: "browser".into(),
|
||||
};
|
||||
|
||||
let inserted_mod = User_::create(&conn, &new_mod).unwrap();
|
||||
|
@ -466,6 +467,7 @@ mod tests {
|
|||
theme: "darkly".into(),
|
||||
default_sort_type: SortType::Hot as i16,
|
||||
default_listing_type: ListingType::Subscribed as i16,
|
||||
lang: "browser".into(),
|
||||
};
|
||||
|
||||
let inserted_user = User_::create(&conn, &new_user).unwrap();
|
||||
|
|
|
@ -92,6 +92,7 @@ mod tests {
|
|||
theme: "darkly".into(),
|
||||
default_sort_type: SortType::Hot as i16,
|
||||
default_listing_type: ListingType::Subscribed as i16,
|
||||
lang: "browser".into(),
|
||||
};
|
||||
|
||||
let inserted_user = User_::create(&conn, &new_user).unwrap();
|
||||
|
|
|
@ -194,6 +194,7 @@ mod tests {
|
|||
theme: "darkly".into(),
|
||||
default_sort_type: SortType::Hot as i16,
|
||||
default_listing_type: ListingType::Subscribed as i16,
|
||||
lang: "browser".into(),
|
||||
};
|
||||
|
||||
let inserted_user = User_::create(&conn, &new_user).unwrap();
|
||||
|
|
|
@ -345,6 +345,7 @@ mod tests {
|
|||
theme: "darkly".into(),
|
||||
default_sort_type: SortType::Hot as i16,
|
||||
default_listing_type: ListingType::Subscribed as i16,
|
||||
lang: "browser".into(),
|
||||
};
|
||||
|
||||
let inserted_user = User_::create(&conn, &new_user).unwrap();
|
||||
|
|
|
@ -23,6 +23,7 @@ pub struct User_ {
|
|||
pub theme: String,
|
||||
pub default_sort_type: i16,
|
||||
pub default_listing_type: i16,
|
||||
pub lang: String,
|
||||
}
|
||||
|
||||
#[derive(Insertable, AsChangeset, Clone)]
|
||||
|
@ -40,6 +41,7 @@ pub struct UserForm {
|
|||
pub theme: String,
|
||||
pub default_sort_type: i16,
|
||||
pub default_listing_type: i16,
|
||||
pub lang: String,
|
||||
}
|
||||
|
||||
impl Crud<UserForm> for User_ {
|
||||
|
@ -96,6 +98,7 @@ pub struct Claims {
|
|||
pub theme: String,
|
||||
pub default_sort_type: i16,
|
||||
pub default_listing_type: i16,
|
||||
pub lang: String,
|
||||
}
|
||||
|
||||
impl Claims {
|
||||
|
@ -119,6 +122,7 @@ impl User_ {
|
|||
theme: self.theme.to_owned(),
|
||||
default_sort_type: self.default_sort_type,
|
||||
default_listing_type: self.default_listing_type,
|
||||
lang: self.lang.to_owned(),
|
||||
};
|
||||
encode(
|
||||
&Header::default(),
|
||||
|
@ -175,6 +179,7 @@ mod tests {
|
|||
theme: "darkly".into(),
|
||||
default_sort_type: SortType::Hot as i16,
|
||||
default_listing_type: ListingType::Subscribed as i16,
|
||||
lang: "browser".into(),
|
||||
};
|
||||
|
||||
let inserted_user = User_::create(&conn, &new_user).unwrap();
|
||||
|
@ -195,6 +200,7 @@ mod tests {
|
|||
theme: "darkly".into(),
|
||||
default_sort_type: SortType::Hot as i16,
|
||||
default_listing_type: ListingType::Subscribed as i16,
|
||||
lang: "browser".into(),
|
||||
};
|
||||
|
||||
let read_user = User_::read(&conn, inserted_user.id).unwrap();
|
||||
|
|
|
@ -75,6 +75,7 @@ mod tests {
|
|||
theme: "darkly".into(),
|
||||
default_sort_type: SortType::Hot as i16,
|
||||
default_listing_type: ListingType::Subscribed as i16,
|
||||
lang: "browser".into(),
|
||||
};
|
||||
|
||||
let inserted_user = User_::create(&conn, &new_user).unwrap();
|
||||
|
@ -92,6 +93,7 @@ mod tests {
|
|||
theme: "darkly".into(),
|
||||
default_sort_type: SortType::Hot as i16,
|
||||
default_listing_type: ListingType::Subscribed as i16,
|
||||
lang: "browser".into(),
|
||||
};
|
||||
|
||||
let inserted_recipient = User_::create(&conn, &recipient_form).unwrap();
|
||||
|
|
|
@ -266,6 +266,7 @@ table! {
|
|||
theme -> Varchar,
|
||||
default_sort_type -> Int2,
|
||||
default_listing_type -> Int2,
|
||||
lang -> Varchar,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
35
ui/src/components/user.tsx
vendored
35
ui/src/components/user.tsx
vendored
|
@ -27,6 +27,7 @@ import {
|
|||
capitalizeFirstLetter,
|
||||
themes,
|
||||
setTheme,
|
||||
languages,
|
||||
} from '../utils';
|
||||
import { PostListing } from './post-listing';
|
||||
import { SortSelect } from './sort-select';
|
||||
|
@ -94,6 +95,7 @@ export class User extends Component<any, UserState> {
|
|||
theme: null,
|
||||
default_sort_type: null,
|
||||
default_listing_type: null,
|
||||
lang: null,
|
||||
auth: null,
|
||||
},
|
||||
userSettingsLoading: null,
|
||||
|
@ -420,6 +422,32 @@ export class User extends Component<any, UserState> {
|
|||
<T i18nKey="settings">#</T>
|
||||
</h5>
|
||||
<form onSubmit={linkEvent(this, this.handleUserSettingsSubmit)}>
|
||||
<div class="form-group">
|
||||
<div class="col-12">
|
||||
<label>
|
||||
<T i18nKey="language">#</T>
|
||||
</label>
|
||||
<select
|
||||
value={this.state.userSettingsForm.lang}
|
||||
onChange={linkEvent(
|
||||
this,
|
||||
this.handleUserSettingsLangChange
|
||||
)}
|
||||
class="ml-2 custom-select custom-select-sm w-auto"
|
||||
>
|
||||
<option disabled>
|
||||
<T i18nKey="language">#</T>
|
||||
</option>
|
||||
<option value="browser">
|
||||
<T i18nKey="browser_default">#</T>
|
||||
</option>
|
||||
<option disabled>──</option>
|
||||
{languages.map(lang => (
|
||||
<option value={lang.code}>{lang.name}</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-12">
|
||||
<label>
|
||||
|
@ -693,6 +721,12 @@ export class User extends Component<any, UserState> {
|
|||
i.setState(i.state);
|
||||
}
|
||||
|
||||
handleUserSettingsLangChange(i: User, event: any) {
|
||||
i.state.userSettingsForm.lang = event.target.value;
|
||||
i18n.changeLanguage(i.state.userSettingsForm.lang);
|
||||
i.setState(i.state);
|
||||
}
|
||||
|
||||
handleUserSettingsSortTypeChange(val: SortType) {
|
||||
this.state.userSettingsForm.default_sort_type = val;
|
||||
this.setState(this.state);
|
||||
|
@ -762,6 +796,7 @@ export class User extends Component<any, UserState> {
|
|||
UserService.Instance.user.default_sort_type;
|
||||
this.state.userSettingsForm.default_listing_type =
|
||||
UserService.Instance.user.default_listing_type;
|
||||
this.state.userSettingsForm.lang = UserService.Instance.user.lang;
|
||||
}
|
||||
document.title = `/u/${this.state.user.name} - ${WebSocketService.Instance.site.name}`;
|
||||
window.scrollTo(0, 0);
|
||||
|
|
2
ui/src/interfaces.ts
vendored
2
ui/src/interfaces.ts
vendored
|
@ -79,6 +79,7 @@ export interface User {
|
|||
theme: string;
|
||||
default_sort_type: SortType;
|
||||
default_listing_type: ListingType;
|
||||
lang: string;
|
||||
}
|
||||
|
||||
export interface UserView {
|
||||
|
@ -469,6 +470,7 @@ export interface UserSettingsForm {
|
|||
theme: string;
|
||||
default_sort_type: SortType;
|
||||
default_listing_type: ListingType;
|
||||
lang: string;
|
||||
auth: string;
|
||||
}
|
||||
|
||||
|
|
2
ui/src/translations/en.ts
vendored
2
ui/src/translations/en.ts
vendored
|
@ -125,6 +125,8 @@ export const en = {
|
|||
email: 'Email',
|
||||
optional: 'Optional',
|
||||
expires: 'Expires',
|
||||
language: 'Language',
|
||||
browser_default: 'Browser Default',
|
||||
url: 'URL',
|
||||
body: 'Body',
|
||||
copy_suggested_title: 'copy suggested title: {{title}}',
|
||||
|
|
39
ui/src/utils.ts
vendored
39
ui/src/utils.ts
vendored
|
@ -16,6 +16,7 @@ import {
|
|||
ListingType,
|
||||
SearchType,
|
||||
} from './interfaces';
|
||||
import { UserService } from './services/UserService';
|
||||
import * as markdown_it from 'markdown-it';
|
||||
import * as markdownitEmoji from 'markdown-it-emoji/light';
|
||||
import * as markdown_it_container from 'markdown-it-container';
|
||||
|
@ -240,16 +241,32 @@ export function debounce(
|
|||
};
|
||||
}
|
||||
|
||||
export const languages = [
|
||||
{ code: 'en', name: 'English' },
|
||||
{ code: 'eo', name: 'Esperanto' },
|
||||
{ code: 'es', name: 'Español' },
|
||||
{ code: 'de', name: 'Deutsch' },
|
||||
{ code: 'zh', name: '中文' },
|
||||
{ code: 'fr', name: 'Français' },
|
||||
{ code: 'sv', name: 'Svenska' },
|
||||
{ code: 'ru', name: 'Русский' },
|
||||
{ code: 'nl', name: 'Nederlands' },
|
||||
{ code: 'it', name: 'Italiano' },
|
||||
];
|
||||
|
||||
export function getLanguage(): string {
|
||||
return navigator.language || navigator.userLanguage;
|
||||
let user = UserService.Instance.user;
|
||||
let lang = user && user.lang ? user.lang : 'browser';
|
||||
|
||||
if (lang == 'browser') {
|
||||
return getBrowserLanguage();
|
||||
} else {
|
||||
return lang;
|
||||
}
|
||||
}
|
||||
|
||||
export function objectFlip(obj: any) {
|
||||
const ret = {};
|
||||
Object.keys(obj).forEach(key => {
|
||||
ret[obj[key]] = key;
|
||||
});
|
||||
return ret;
|
||||
export function getBrowserLanguage(): string {
|
||||
return navigator.language || navigator.userLanguage;
|
||||
}
|
||||
|
||||
export function getMomentLanguage(): string {
|
||||
|
@ -313,3 +330,11 @@ export function setTheme(theme: string = 'darkly') {
|
|||
}
|
||||
document.getElementById(theme).removeAttribute('disabled');
|
||||
}
|
||||
|
||||
export function objectFlip(obj: any) {
|
||||
const ret = {};
|
||||
Object.keys(obj).forEach(key => {
|
||||
ret[obj[key]] = key;
|
||||
});
|
||||
return ret;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue