mirror of
https://github.com/discourse/discourse.git
synced 2024-11-23 03:59:50 +08:00
Merge branch 'master' into vdom
This commit is contained in:
commit
c404da248a
|
@ -1,6 +1,6 @@
|
|||
[main]
|
||||
host = https://www.transifex.com
|
||||
lang_map = es_ES: es, fr_FR: fr, ko_KR: ko, pt_PT: pt, sk_SK: sk
|
||||
lang_map = es_ES: es, fr_FR: fr, ko_KR: ko, pt_PT: pt, sk_SK: sk, vi_VN: vi
|
||||
|
||||
[discourse-org.clientenyml]
|
||||
file_filter = config/locales/client.<lang>.yml
|
||||
|
|
|
@ -69,6 +69,9 @@ export default Ember.Controller.extend(ModalFunctionality, {
|
|||
sentTo: result.sent_to_email,
|
||||
currentEmail: result.current_email
|
||||
});
|
||||
} else if (result.reason === 'suspended' ) {
|
||||
self.send("closeModal");
|
||||
bootbox.alert(result.error);
|
||||
} else {
|
||||
self.flash(result.error, 'error');
|
||||
}
|
||||
|
|
|
@ -261,8 +261,10 @@ class SessionController < ApplicationController
|
|||
def failed_to_login(user)
|
||||
message = user.suspend_reason ? "login.suspended_with_reason" : "login.suspended"
|
||||
|
||||
render json: { error: I18n.t(message, { date: I18n.l(user.suspended_till, format: :date_only),
|
||||
reason: user.suspend_reason}) }
|
||||
render json: {
|
||||
error: I18n.t(message, { date: I18n.l(user.suspended_till, format: :date_only), reason: user.suspend_reason}),
|
||||
reason: 'suspended'
|
||||
}
|
||||
end
|
||||
|
||||
def login(user)
|
||||
|
|
|
@ -11,8 +11,14 @@ module Jobs
|
|||
PostAction.flagged_posts_count > 0 &&
|
||||
FlagQuery.flagged_post_actions('active').where('post_actions.created_at < ?', SiteSetting.notify_about_flags_after.to_i.hours.ago).pluck(:id).count > 0
|
||||
|
||||
message = PendingFlagsMailer.notify
|
||||
Email::Sender.new(message, :pending_flags_reminder).send
|
||||
PostCreator.create(
|
||||
Discourse.system_user,
|
||||
target_group_names: ["staff"],
|
||||
archetype: Archetype.private_message,
|
||||
subtype: TopicSubtype.system_message,
|
||||
title: I18n.t('flags_reminder.subject_template', { count: PostAction.flagged_posts_count }),
|
||||
raw: I18n.t('flags_reminder.flags_were_submitted', { count: SiteSetting.notify_about_flags_after })
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
class UserProfile < ActiveRecord::Base
|
||||
belongs_to :user, inverse_of: :user_profile
|
||||
|
||||
WEBSITE_REGEXP = /(^$)|(^(http|https):\/\/[a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,9}(([0-9]{1,5})?\/.*)?$)/ix
|
||||
|
||||
validates :bio_raw, length: { maximum: 3000 }
|
||||
validates :website, format: { with: /(^$)|(^(http|https):\/\/[a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,9}(([0-9]{1,5})?\/.*)?$)/ix }, allow_blank: true
|
||||
validates :website, format: { with: WEBSITE_REGEXP }, allow_blank: true
|
||||
validates :user, presence: true
|
||||
before_save :cook
|
||||
after_save :trigger_badges
|
||||
|
|
|
@ -2116,11 +2116,11 @@ en:
|
|||
is_disabled: "Restore is disabled in the site settings."
|
||||
label: "Restore"
|
||||
title: "Restore the backup"
|
||||
confirm: "Are your sure you want to restore this backup?"
|
||||
confirm: "Are you sure you want to restore this backup?"
|
||||
rollback:
|
||||
label: "Rollback"
|
||||
title: "Rollback the database to previous working state"
|
||||
confirm: "Are your sure you want to rollback the database to the previous working state?"
|
||||
confirm: "Are you sure you want to rollback the database to the previous working state?"
|
||||
|
||||
export_csv:
|
||||
user_archive_confirm: "Are you sure you want to download your posts?"
|
||||
|
|
2089
config/locales/client.vi.yml
Normal file
2089
config/locales/client.vi.yml
Normal file
File diff suppressed because it is too large
Load Diff
|
@ -1406,6 +1406,14 @@ en:
|
|||
blocked: "New registrations are not allowed from your IP address."
|
||||
max_new_accounts_per_registration_ip: "New registrations are not allowed from your IP address (maximum limit reached). Contact a staff member."
|
||||
|
||||
flags_reminder:
|
||||
flags_were_submitted:
|
||||
one: "Flags were submitted over 1 hour ago. Please review them."
|
||||
other: "Flags were submitted over %{count} hours ago. Please review them."
|
||||
subject_template:
|
||||
one: "1 flag waiting to be handled"
|
||||
other: "%{count} flags waiting to be handled"
|
||||
|
||||
unsubscribe_mailer:
|
||||
subject_template: "Confirm you no longer want to receive email updates from %{site_title}"
|
||||
text_body_template: |
|
||||
|
@ -1482,6 +1490,8 @@ en:
|
|||
|
||||
- If you run your own mail server, check to make sure the IPs of your mail server are [not on any email blacklists][4]. Also verify that it is definitely sending a fully-qualified hostname that resolves in DNS in its HELO message. If not, this will cause your email to be rejected by many mail services.
|
||||
|
||||
- Send a test email to [mail-tester.com][mt] to verify that everything is working correctly.
|
||||
|
||||
(The *easy* way is to create a free account on [Mandrill][md] or [Mailgun][mg] or [Mailjet][mj], which have free generous free mailing plans and will be fine for small communities. You'll still need to set up the SPF and DKIM records in your DNS, though!)
|
||||
|
||||
We hope you received this email deliverability test OK!
|
||||
|
@ -1500,6 +1510,7 @@ en:
|
|||
[md]: http://mandrill.com
|
||||
[mg]: http://www.mailgun.com/
|
||||
[mj]: https://www.mailjet.com/pricing
|
||||
[mt]: http://www.mail-tester.com/
|
||||
|
||||
new_version_mailer:
|
||||
subject_template: "[%{site_name}] New Discourse version, update available"
|
||||
|
@ -1537,17 +1548,6 @@ en:
|
|||
|
||||
%{notes}
|
||||
|
||||
flags_reminder:
|
||||
flags_were_submitted:
|
||||
one: "These flags were submitted over 1 hour ago."
|
||||
other: "These flags were submitted over %{count} hours ago."
|
||||
please_review: "Please review them."
|
||||
post_number: "post"
|
||||
how_to_disable: 'You can disable or change the frequency of this email reminder via the "notify about flags after" setting.'
|
||||
subject_template:
|
||||
one: "1 flag waiting to be handled"
|
||||
other: "%{count} flags waiting to be handled"
|
||||
|
||||
queued_posts_reminder:
|
||||
subject_template:
|
||||
one: "[%{site_name}] 1 post waiting to be reviewed"
|
||||
|
|
1028
config/locales/server.vi.yml
Normal file
1028
config/locales/server.vi.yml
Normal file
File diff suppressed because it is too large
Load Diff
|
@ -42,14 +42,21 @@ module UserNameSuggester
|
|||
# 2. removes unallowed leading characters
|
||||
name.gsub!(/^\W+/, "")
|
||||
# 3. removes unallowed trailing characters
|
||||
name.gsub!(/[^A-Za-z0-9]+$/, "")
|
||||
name = remove_unallowed_trailing_characters(name)
|
||||
# 4. unify special characters
|
||||
name.gsub!(/[-_.]{2,}/, "_")
|
||||
name
|
||||
end
|
||||
|
||||
def self.remove_unallowed_trailing_characters(name)
|
||||
name.gsub!(/[^A-Za-z0-9]+$/, "")
|
||||
name
|
||||
end
|
||||
|
||||
def self.rightsize_username(name)
|
||||
name.ljust(User.username_length.begin, '1')[0, User.username_length.end]
|
||||
name = name[0, User.username_length.end]
|
||||
name = remove_unallowed_trailing_characters(name)
|
||||
name.ljust(User.username_length.begin, '1')
|
||||
end
|
||||
|
||||
end
|
||||
|
|
31
plugins/poll/config/locales/client.vi.yml
Normal file
31
plugins/poll/config/locales/client.vi.yml
Normal file
|
@ -0,0 +1,31 @@
|
|||
vi:
|
||||
js:
|
||||
poll:
|
||||
voters:
|
||||
other: "người bình chọn"
|
||||
total_votes:
|
||||
other: "tổng số bình chọn"
|
||||
average_rating: "Đánh giá trung bình: <strong>%{average}</strong>."
|
||||
multiple:
|
||||
help:
|
||||
between_min_and_max_options: "Bạn có thể chọn giữa <strong>%{min}</strong> và <strong>%{max}</strong>."
|
||||
cast-votes:
|
||||
title: "Bỏ phiếu của bạn"
|
||||
label: "Bình chọn ngay!"
|
||||
show-results:
|
||||
title: "Hiển thị kết quả cuộc thăm dò"
|
||||
label: "Hiện kết quả"
|
||||
hide-results:
|
||||
title: "Trở lại bầu chọn của bạn"
|
||||
label: "Ẩn kết quả"
|
||||
open:
|
||||
title: "Mở bình chọn"
|
||||
label: "Mở"
|
||||
confirm: "Bạn có chắc mở bình chọn này?"
|
||||
close:
|
||||
title: "Đóng bình chọn"
|
||||
label: "Đóng lại"
|
||||
confirm: "Bạn có chắc chắn muốn đóng bình chọn này?"
|
||||
error_while_toggling_status: "Có lỗi trong khi chuyển đổi qua lại các trạng thái của bình chọn này."
|
||||
error_while_casting_votes: "Có lỗi trong khi tạo mãu bầu chọn của bạn"
|
||||
|
25
plugins/poll/config/locales/server.vi.yml
Normal file
25
plugins/poll/config/locales/server.vi.yml
Normal file
|
@ -0,0 +1,25 @@
|
|||
vi:
|
||||
site_settings:
|
||||
poll_enabled: "Cho phép người dùng tạo các cuộc thăm dò?"
|
||||
poll_maximum_options: "Số lượng tối đa tùy chọn trong một cuộc thăm dò."
|
||||
poll:
|
||||
multiple_polls_without_name: "Có nhiều cuộc thăm dò mà không có tên. Sử dụng thuộc tính '<code>name</code>' để xác định cuộc thăm dò của bạn."
|
||||
multiple_polls_with_same_name: "Có nhiều cuộc thăm dò có cùng tên: <strong>%{name}</strong>. Sử dụng thuộc tính '<code>name</code>' để xác định cuộc thăm dò của bạn."
|
||||
default_poll_must_have_at_least_2_options: "Thăm dò ý kiến phải có ít nhất 2 lựa chọn."
|
||||
named_poll_must_have_at_least_2_options: "Thăm dò có tên <strong>%{name}</strong> phải có ít nhất 2 lựa chọn."
|
||||
default_poll_must_have_different_options: "Thăm dò ý kiến phải có các tùy chọn khác nhau."
|
||||
named_poll_must_have_different_options: "Thăm dò <strong>%{name}</strong> phải có các tùy chọn khác nhau."
|
||||
default_poll_with_multiple_choices_has_invalid_parameters: "Thăm dò ý kiến với nhiều sự lựa chọn có các tham số không hợp lệ."
|
||||
named_poll_with_multiple_choices_has_invalid_parameters: "Thăm dò <strong>%{name}</strong> với nhiều sự lựa chọn có các tham số không hợp lệ. "
|
||||
requires_at_least_1_valid_option: "Bạn phải chọn ít nhất 1 lựa chọn hợp lệ."
|
||||
cannot_change_polls_after_5_minutes: "Bạn không thể thêm, xóa hoặc đổi tên các cuộc thăm dò 5 phút đầu tiên."
|
||||
op_cannot_edit_options_after_5_minutes: "Bạn không thể thêm hoặc loại bỏ các bình chọn sau khi 5 phút đầu tiên. Hãy liên hệ với người điều hành nếu bạn cần chỉnh sửa một bình chọn nào đó."
|
||||
staff_cannot_add_or_remove_options_after_5_minutes: "Bạn không thể thêm hoặc loại bỏ các bình chọn sau khi 5 phút đầu tiên. Bạn nên đóng chủ đề này và tạo ra một cái mới để thay thế."
|
||||
no_polls_associated_with_this_post: "Không có cuộc thăm dò được liên kết với bài này."
|
||||
no_poll_with_this_name: "Không có thăm dò có tên <strong>%{name}</strong> liên kết với bài viết này."
|
||||
post_is_deleted: "Không thể thực hiện trên bài viết đã xóa."
|
||||
topic_must_be_open_to_vote: "Các chủ đề phải được mở để bầu chọn."
|
||||
poll_must_be_open_to_vote: "Thăm dò ý kiến phải được mở để bầu chọn."
|
||||
topic_must_be_open_to_toggle_status: "Các chủ đề phải được mở để chuyển trạng thái."
|
||||
only_staff_or_op_can_toggle_status: "Chỉ có một BQT hoặc các người đăng bài có thể chuyển đổi một trạng thái thăm dò ý kiến"
|
||||
|
27
public/403.vi.html
Normal file
27
public/403.vi.html
Normal file
|
@ -0,0 +1,27 @@
|
|||
<html>
|
||||
<head>
|
||||
<title> Bạn không thể làm được điều đó (403)</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||||
<style type="text/css">
|
||||
body { background-color: #fff; color: #666; text-align: center; font-family: arial, sans-serif; }
|
||||
div.dialog {
|
||||
width: 25em;
|
||||
padding: 0 4em;
|
||||
margin: 4em auto 0 auto;
|
||||
border: 1px solid #ccc;
|
||||
border-right-color: #999;
|
||||
border-bottom-color: #999;
|
||||
}
|
||||
h1 { font-size: 400%; color: #f00; line-height: 1em; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="dialog">
|
||||
<h1>403</h1>
|
||||
<p>Bạn không thể xem tài nguyên đó!</p>
|
||||
|
||||
<p>Trang này sẽ được thay thế bằng một trang lỗi 403 tùy chỉnh của Discourse.</p>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
26
public/422.vi.html
Normal file
26
public/422.vi.html
Normal file
|
@ -0,0 +1,26 @@
|
|||
<html>
|
||||
<head>
|
||||
<title>Thay đổi bạn muốn thực hiện đã bị từ chối (422)</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||||
<style type="text/css">
|
||||
body { background-color: #fff; color: #666; text-align: center; font-family: arial, sans-serif; }
|
||||
div.dialog {
|
||||
width: 25em;
|
||||
padding: 0 4em;
|
||||
margin: 4em auto 0 auto;
|
||||
border: 1px solid #ccc;
|
||||
border-right-color: #999;
|
||||
border-bottom-color: #999;
|
||||
}
|
||||
h1 { font-size: 100%; color: #f00; line-height: 1.5em; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<!-- This file lives in public/422.html -->
|
||||
<div class="dialog">
|
||||
<h1>Thay đổi bạn muốn thực hiện đã bị từ chối.</h1>
|
||||
<p>Có thể bạn đã cố thay đổi một số tính năng mà bạn không thể truy cập.</p>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
13
public/500.vi.html
Normal file
13
public/500.vi.html
Normal file
|
@ -0,0 +1,13 @@
|
|||
<html>
|
||||
<head>
|
||||
<title>Ôi - Lỗi 500</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||||
</head>
|
||||
<body>
|
||||
<h1>Ối</h1>
|
||||
<p>Phần mềm chạy diễn đàn thảo luận này bất ngờ gặp sự cố không mong muốn. Chúng tôi rất xin lỗi vì sự bất tiện này.</p>
|
||||
<p>Thông tin chi tiết về lỗi đã được ghi lại và thông báo tự động đã được tạo. Chúng tôi sẽ xem xét lỗi này.</p>
|
||||
<p>Không cần tiến hành bất cứ hành động nào. Tuy nhiên, nếu lỗi này vẫn tiếp tục, bạn có thể cung cấp thêm thông tin chi tiết bao gồm các bước để tái tạo lỗi hoặc tạo một thảo luận trên <a href="/category/meta">meta category</a>.</p>
|
||||
</body>
|
||||
</html>
|
||||
|
12
public/503.vi.html
Normal file
12
public/503.vi.html
Normal file
|
@ -0,0 +1,12 @@
|
|||
<html>
|
||||
<head>
|
||||
<title>Trang đang được bảo trì- Discourse.org</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||||
</head>
|
||||
<body>
|
||||
<h1>Trang tạm dừng dịch vụ để bảo trì dịch vụ</h1>
|
||||
<p>Vui lòng quay lại sau <span id="when-to-check-back">vài phút</span>.</p>
|
||||
<p id="apology">Xin lỗi về sự bất tiện này!</p>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -278,7 +278,6 @@ class ImportScripts::Base
|
|||
avatar_url = opts.delete(:avatar_url)
|
||||
|
||||
# Allow the || operations to work with empty strings ''
|
||||
opts[:name] = nil if opts[:name].blank?
|
||||
opts[:username] = nil if opts[:username].blank?
|
||||
|
||||
opts[:name] = User.suggest_name(opts[:email]) unless opts[:name]
|
||||
|
@ -287,7 +286,8 @@ class ImportScripts::Base
|
|||
opts[:username].length > User.username_length.end ||
|
||||
!User.username_available?(opts[:username]) ||
|
||||
!UsernameValidator.new(opts[:username]).valid_format?
|
||||
opts[:username] = UserNameSuggester.suggest(opts[:username] || opts[:name] || opts[:email])
|
||||
|
||||
opts[:username] = UserNameSuggester.suggest(opts[:username] || opts[:name].presence || opts[:email])
|
||||
end
|
||||
opts[:email] = opts[:email].downcase
|
||||
opts[:trust_level] = TrustLevel[1] unless opts[:trust_level]
|
||||
|
@ -306,8 +306,8 @@ class ImportScripts::Base
|
|||
User.transaction do
|
||||
u.save!
|
||||
if bio_raw.present? || website.present? || location.present?
|
||||
u.user_profile.bio_raw = bio_raw if bio_raw.present?
|
||||
u.user_profile.website = website if website.present?
|
||||
u.user_profile.bio_raw = bio_raw[0..2999] if bio_raw.present?
|
||||
u.user_profile.website = website unless website.blank? || website !~ UserProfile::WEBSITE_REGEXP
|
||||
u.user_profile.location = location if location.present?
|
||||
u.user_profile.save!
|
||||
end
|
||||
|
|
|
@ -93,6 +93,15 @@ describe UserNameSuggester do
|
|||
it 'should handle typical facebook usernames' do
|
||||
expect(UserNameSuggester.suggest('roger.nelson.3344913')).to eq('roger.nelson.33')
|
||||
end
|
||||
|
||||
it 'removes underscore at the end of long usernames that get truncated' do
|
||||
expect(UserNameSuggester.suggest('uuuuuuuuuuuuuu_u')).to_not end_with('_')
|
||||
end
|
||||
|
||||
it "adds number if it's too short after removing trailing underscore" do
|
||||
User.stubs(:username_length).returns(8..8)
|
||||
expect(UserNameSuggester.suggest('uuuuuuu_u')).to eq('uuuuuuu1')
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -14,17 +14,17 @@ describe Jobs::PendingFlagsReminder do
|
|||
context "notify_about_flags_after is 48" do
|
||||
before { SiteSetting.stubs(:notify_about_flags_after).returns(48) }
|
||||
|
||||
it "doesn't send email when flags are less than 48 hours old" do
|
||||
it "doesn't send message when flags are less than 48 hours old" do
|
||||
Fabricate(:flag, created_at: 47.hours.ago)
|
||||
PostAction.stubs(:flagged_posts_count).returns(1)
|
||||
Email::Sender.any_instance.expects(:send).never
|
||||
PostCreator.expects(:create).never
|
||||
described_class.new.execute({})
|
||||
end
|
||||
|
||||
it "sends email when there is a flag older than 48 hours" do
|
||||
it "sends message when there is a flag older than 48 hours" do
|
||||
Fabricate(:flag, created_at: 49.hours.ago)
|
||||
PostAction.stubs(:flagged_posts_count).returns(1)
|
||||
Email::Sender.any_instance.expects(:send).once.returns(true)
|
||||
PostCreator.expects(:create).once.returns(true)
|
||||
described_class.new.execute({})
|
||||
end
|
||||
end
|
||||
|
|
6
vendor/gems/discourse_imgur/lib/discourse_imgur/locale/server.vi.yml
vendored
Normal file
6
vendor/gems/discourse_imgur/lib/discourse_imgur/locale/server.vi.yml
vendored
Normal file
|
@ -0,0 +1,6 @@
|
|||
vi:
|
||||
site_settings:
|
||||
enable_imgur: "Kích hoạt imgur api để tải file lên, không lưu trữ file tại máy chủ."
|
||||
imgur_client_id: "Client ID imgur.com của bạn, cần cho chức năng tải ảnh lên. "
|
||||
imgur_client_secret: "Client secret của bạn tạo imgur.com. Hiện tại không cần để tải ảnh lên, nhưng sẽ có trong tương lai."
|
||||
|
Loading…
Reference in New Issue
Block a user