diff --git a/js/forum/src/components/DiscussionListItem.js b/js/forum/src/components/DiscussionListItem.js
index 935aa0af7..a3cce4719 100644
--- a/js/forum/src/components/DiscussionListItem.js
+++ b/js/forum/src/components/DiscussionListItem.js
@@ -174,8 +174,12 @@ export default class DiscussionListItem extends Component {
const discussion = this.props.discussion;
if (discussion.isUnread()) {
- discussion.save({readNumber: discussion.lastPostNumber()});
- m.redraw();
+ const confirmation = confirm(app.translator.trans('core.forum.discussion_list.mark_all_as_read_confirmation'));
+
+ if (confirmation) {
+ discussion.save({readNumber: discussion.lastPostNumber()});
+ m.redraw();
+ }
}
}
diff --git a/js/forum/src/components/IndexPage.js b/js/forum/src/components/IndexPage.js
index 5848520f0..d85867b94 100644
--- a/js/forum/src/components/IndexPage.js
+++ b/js/forum/src/components/IndexPage.js
@@ -358,6 +358,10 @@ export default class IndexPage extends Page {
* @return void
*/
markAllAsRead() {
- app.session.user.save({readTime: new Date()});
+ const confirmation = confirm(app.translator.trans('core.forum.index.mark_all_as_read_confirmation'));
+
+ if (confirmation) {
+ app.session.user.save({readTime: new Date()});
+ }
}
}
diff --git a/js/forum/src/components/PostStream.js b/js/forum/src/components/PostStream.js
index d18cec577..5fc1cff41 100644
--- a/js/forum/src/components/PostStream.js
+++ b/js/forum/src/components/PostStream.js
@@ -55,7 +55,9 @@ class PostStream extends Component {
return this.goToLast().then(() => {
$('html,body').stop(true).animate({
scrollTop: $(document).height() - $(window).height()
- }, 'fast');
+ }, 'fast', () => {
+ this.flashItem(this.$('.PostStream-item:last-child'));
+ });
});
}
diff --git a/js/lib/models/User.js b/js/lib/models/User.js
index a1b231654..cd7ead7be 100644
--- a/js/lib/models/User.js
+++ b/js/lib/models/User.js
@@ -17,7 +17,7 @@ Object.assign(User.prototype, {
avatarUrl: Model.attribute('avatarUrl'),
bio: Model.attribute('bio'),
- bioHtml: computed('bio', bio => bio ? '
' + $('
').text(bio).html().replace(/\n/g, '
').autoLink() + '' : ''),
+ bioHtml: computed('bio', bio => bio ? '' + $('
').text(bio).html().replace(/\n/g, '
').autoLink({rel: 'nofollow'}) + '' : ''),
preferences: Model.attribute('preferences'),
groups: Model.hasMany('groups'),
diff --git a/less/lib/lib.less b/less/lib/lib.less
index b942aa28d..45396ecd3 100755
--- a/less/lib/lib.less
+++ b/less/lib/lib.less
@@ -1,5 +1,3 @@
-@import url(//fonts.googleapis.com/css?family=Open+Sans:400italic,700italic,400,700,600);
-
@import "font-awesome.less";
@fa-font-path: "../../assets/fonts";
diff --git a/src/Api/ApiServiceProvider.php b/src/Api/ApiServiceProvider.php
index 09012694b..acd114fdf 100644
--- a/src/Api/ApiServiceProvider.php
+++ b/src/Api/ApiServiceProvider.php
@@ -110,13 +110,6 @@ class ApiServiceProvider extends AbstractServiceProvider
$toController('Flarum\Api\Controller\ShowForumController')
);
- // Save forum information
- $routes->patch(
- '/forum',
- 'forum.update',
- $toController('Flarum\Api\Controller\UpdateForumController')
- );
-
// Retrieve authentication token
$routes->post(
'/token',
diff --git a/src/Event/ConfigureLocales.php b/src/Event/ConfigureLocales.php
index 8ecf98518..c37e84c49 100644
--- a/src/Event/ConfigureLocales.php
+++ b/src/Event/ConfigureLocales.php
@@ -10,7 +10,9 @@
namespace Flarum\Event;
+use DirectoryIterator;
use Flarum\Locale\LocaleManager;
+use RuntimeException;
class ConfigureLocales
{
@@ -26,4 +28,45 @@ class ConfigureLocales
{
$this->locales = $locales;
}
+
+ /**
+ * Load language pack resources from the given directory.
+ *
+ * @param $directory
+ */
+ public function loadLanguagePackFrom($directory)
+ {
+ $name = $title = basename($directory);
+
+ if (file_exists($manifest = $directory.'/composer.json')) {
+ $json = json_decode(file_get_contents($manifest), true);
+
+ if (empty($json)) {
+ throw new RuntimeException("Error parsing composer.json in $name: ".json_last_error_msg());
+ }
+
+ $locale = array_get($json, 'extra.flarum-locale.code');
+ $title = array_get($json, 'extra.flarum-locale.title', $title);
+ }
+
+ if (! isset($locale)) {
+ throw new RuntimeException("Language pack $name must define \"extra.flarum-locale.code\" in composer.json.");
+ }
+
+ $this->locales->addLocale($locale, $title);
+
+ if (! is_dir($localeDir = $directory.'/locale')) {
+ throw new RuntimeException("Language pack $name must have a \"locale\" subdirectory.");
+ }
+
+ if (file_exists($file = $localeDir.'/config.js')) {
+ $this->locales->addJsFile($locale, $file);
+ }
+
+ foreach (new DirectoryIterator($localeDir) as $file) {
+ if ($file->isFile() && in_array($file->getExtension(), ['yml', 'yaml'])) {
+ $this->locales->addTranslations($locale, $file->getPathname());
+ }
+ }
+ }
}
diff --git a/src/Foundation/AbstractServer.php b/src/Foundation/AbstractServer.php
index 5dfda65c0..6cb669642 100644
--- a/src/Foundation/AbstractServer.php
+++ b/src/Foundation/AbstractServer.php
@@ -78,14 +78,6 @@ abstract class AbstractServer
*/
protected function getApp()
{
- // franzliedke/studio currently doesn't autoload files (see issue
- // below), so we will need to load them manually if we're using studio.
- // https://github.com/franzliedke/studio/issues/29
- if (file_exists($corePath = $this->path.'/core')) {
- require $corePath.'/src/helpers.php';
- require $corePath.'/vendor/swiftmailer/swiftmailer/lib/swift_required.php';
- }
-
date_default_timezone_set('UTC');
$app = new Application($this->path);
diff --git a/src/Http/Controller/ClientView.php b/src/Http/Controller/ClientView.php
index b5f786b1c..97554de88 100644
--- a/src/Http/Controller/ClientView.php
+++ b/src/Http/Controller/ClientView.php
@@ -127,6 +127,8 @@ class ClientView implements Renderable
$this->assets = $assets;
$this->layout = $layout;
$this->localeJs = $localeJs;
+
+ $this->addHeadString('', 'font');
}
/**
@@ -164,9 +166,13 @@ class ClientView implements Renderable
*
* @param string $string
*/
- public function addHeadString($string)
+ public function addHeadString($string, $name = null)
{
- $this->headStrings[] = $string;
+ if ($name) {
+ $this->headStrings[$name] = $string;
+ } else {
+ $this->headStrings[] = $string;
+ }
}
/**