From: nodiscc Date: Sat, 11 Apr 2020 13:06:30 +0000 (+0000) Subject: Merge pull request #1403 from shaarli/doc-composer X-Git-Tag: v0.12.0-beta~11 X-Git-Url: https://git.immae.eu/?a=commitdiff_plain;h=752bc4c5e6a2e525e3b714abfa24e1aa7f6c71ff;hp=2dd6ecb126ed5dd18d9c46ae892a440986239cab;p=github%2Fshaarli%2FShaarli.git Merge pull request #1403 from shaarli/doc-composer doc: simplify composer installation procedure, merge Unit tests related pages, reword/shorten, fix references to old php versions --- diff --git a/Makefile b/Makefile index 917fab7d..b52ba22f 100644 --- a/Makefile +++ b/Makefile @@ -123,7 +123,8 @@ release_tar: composer_dependencies htmldoc translate build_frontend ### generate a release zip and include 3rd-party dependencies and translations release_zip: composer_dependencies htmldoc translate build_frontend git archive --prefix=$(ARCHIVE_PREFIX) -o $(ARCHIVE_VERSION).zip -9 HEAD - mkdir -p $(ARCHIVE_PREFIX)/{doc,vendor} + mkdir -p $(ARCHIVE_PREFIX)/doc + mkdir -p $(ARCHIVE_PREFIX)/vendor rsync -a doc/html/ $(ARCHIVE_PREFIX)doc/html/ zip -r $(ARCHIVE_VERSION).zip $(ARCHIVE_PREFIX)doc/ rsync -a vendor/ $(ARCHIVE_PREFIX)vendor/ @@ -155,6 +156,7 @@ phpdoc: clean htmldoc: python3 -m venv venv/ bash -c 'source venv/bin/activate; \ + pip install wheel; \ pip install mkdocs; \ mkdocs build --clean' find doc/html/ -type f -exec chmod a-x '{}' \; diff --git a/application/Utils.php b/application/Utils.php index 56f5b9a2..4b7fc546 100644 --- a/application/Utils.php +++ b/application/Utils.php @@ -159,7 +159,7 @@ function checkDateFormat($format, $string) */ function generateLocation($referer, $host, $loopTerms = array()) { - $finalReferer = '?'; + $finalReferer = './?'; // No referer if it contains any value in $loopCriteria. foreach (array_filter($loopTerms) as $value) { diff --git a/application/container/ContainerBuilder.php b/application/container/ContainerBuilder.php new file mode 100644 index 00000000..e2c78ccc --- /dev/null +++ b/application/container/ContainerBuilder.php @@ -0,0 +1,81 @@ +conf = $conf; + $this->session = $session; + $this->login = $login; + } + + public function build(): ShaarliContainer + { + $container = new ShaarliContainer(); + $container['conf'] = $this->conf; + $container['sessionManager'] = $this->session; + $container['loginManager'] = $this->login; + $container['plugins'] = function (ShaarliContainer $container): PluginManager { + return new PluginManager($container->conf); + }; + + $container['history'] = function (ShaarliContainer $container): History { + return new History($container->conf->get('resource.history')); + }; + + $container['bookmarkService'] = function (ShaarliContainer $container): BookmarkServiceInterface { + return new BookmarkFileService( + $container->conf, + $container->history, + $container->loginManager->isLoggedIn() + ); + }; + + $container['pageBuilder'] = function (ShaarliContainer $container): PageBuilder { + return new PageBuilder( + $container->conf, + $container->sessionManager->getSession(), + $container->bookmarkService, + $container->sessionManager->generateToken(), + $container->loginManager->isLoggedIn() + ); + }; + + $container['pluginManager'] = function (ShaarliContainer $container): PluginManager { + return new PluginManager($container->conf); + }; + + return $container; + } +} diff --git a/application/container/ShaarliContainer.php b/application/container/ShaarliContainer.php new file mode 100644 index 00000000..3fa9116e --- /dev/null +++ b/application/container/ShaarliContainer.php @@ -0,0 +1,30 @@ +container = $container; + } + + /** + * Middleware execution: + * - execute the controller + * - return the response + * + * In case of error, the error template will be displayed with the exception message. + * + * @param Request $request Slim request + * @param Response $response Slim response + * @param callable $next Next action + * + * @return Response response. + */ + public function __invoke(Request $request, Response $response, callable $next) + { + try { + $response = $next($request, $response); + } catch (ShaarliException $e) { + $this->container->pageBuilder->assign('message', $e->getMessage()); + if ($this->container->conf->get('dev.debug', false)) { + $this->container->pageBuilder->assign( + 'stacktrace', + nl2br(get_class($this) .': '. $e->getTraceAsString()) + ); + } + + $response = $response->withStatus($e->getCode()); + $response = $response->write($this->container->pageBuilder->render('error')); + } + + return $response; + } +} diff --git a/application/front/controllers/LoginController.php b/application/front/controllers/LoginController.php new file mode 100644 index 00000000..ae3599e0 --- /dev/null +++ b/application/front/controllers/LoginController.php @@ -0,0 +1,48 @@ +container->loginManager->isLoggedIn() + || $this->container->conf->get('security.open_shaarli', false) + ) { + return $response->withRedirect('./'); + } + + $userCanLogin = $this->container->loginManager->canLogin($request->getServerParams()); + if ($userCanLogin !== true) { + throw new LoginBannedException(); + } + + if ($request->getParam('username') !== null) { + $this->assignView('username', escape($request->getParam('username'))); + } + + $this + ->assignView('returnurl', escape($request->getServerParam('HTTP_REFERER'))) + ->assignView('remember_user_default', $this->container->conf->get('privacy.remember_user_default', true)) + ->assignView('pagetitle', t('Login') .' - '. $this->container->conf->get('general.title', 'Shaarli')) + ; + + return $response->write($this->render('loginform')); + } +} diff --git a/application/front/controllers/ShaarliController.php b/application/front/controllers/ShaarliController.php new file mode 100644 index 00000000..2b828588 --- /dev/null +++ b/application/front/controllers/ShaarliController.php @@ -0,0 +1,69 @@ +container = $container; + } + + /** + * Assign variables to RainTPL template through the PageBuilder. + * + * @param mixed $value Value to assign to the template + */ + protected function assignView(string $name, $value): self + { + $this->container->pageBuilder->assign($name, $value); + + return $this; + } + + protected function render(string $template): string + { + $this->assignView('linkcount', $this->container->bookmarkService->count(BookmarkFilter::$ALL)); + $this->assignView('privateLinkcount', $this->container->bookmarkService->count(BookmarkFilter::$PRIVATE)); + $this->assignView('plugin_errors', $this->container->pluginManager->getErrors()); + + $this->executeDefaultHooks($template); + + return $this->container->pageBuilder->render($template); + } + + /** + * Call plugin hooks for header, footer and includes, specifying which page will be rendered. + * Then assign generated data to RainTPL. + */ + protected function executeDefaultHooks(string $template): void + { + $common_hooks = [ + 'includes', + 'header', + 'footer', + ]; + + foreach ($common_hooks as $name) { + $plugin_data = []; + $this->container->pluginManager->executeHooks( + 'render_' . $name, + $plugin_data, + [ + 'target' => $template, + 'loggedin' => $this->container->loginManager->isLoggedIn() + ] + ); + $this->assignView('plugins_' . $name, $plugin_data); + } + } +} diff --git a/application/front/exceptions/LoginBannedException.php b/application/front/exceptions/LoginBannedException.php new file mode 100644 index 00000000..b31a4a14 --- /dev/null +++ b/application/front/exceptions/LoginBannedException.php @@ -0,0 +1,15 @@ +tpl->draw($page); } + /** + * Render a specific page as string (using a template file). + * e.g. $pb->render('picwall'); + * + * @param string $page Template filename (without extension). + * + * @return string Processed template content + */ + public function render(string $page): string + { + if ($this->tpl === false) { + $this->initialize(); + } + + return $this->tpl->draw($page, true); + } + /** * Render a 404 page (uses the template : tpl/404.tpl) * usage: $PAGE->render404('The link was deleted') diff --git a/application/security/SessionManager.php b/application/security/SessionManager.php index b8b8ab8d..994fcbe5 100644 --- a/application/security/SessionManager.php +++ b/application/security/SessionManager.php @@ -196,4 +196,10 @@ class SessionManager } return true; } + + /** @return array Local reference to the global $_SESSION array */ + public function getSession(): array + { + return $this->session; + } } diff --git a/assets/default/scss/shaarli.scss b/assets/default/scss/shaarli.scss index cd5dd9e6..243ab1b2 100644 --- a/assets/default/scss/shaarli.scss +++ b/assets/default/scss/shaarli.scss @@ -1236,8 +1236,19 @@ form { color: $dark-grey; } -.page404-container { +.page-error-container { color: $dark-grey; + + h2 { + margin: 70px 0 25px; + } + + pre { + margin: 0 20%; + padding: 20px 0; + text-align: left; + line-height: .7em; + } } // EDIT LINK diff --git a/composer.json b/composer.json index ada06a74..6b670fa2 100644 --- a/composer.json +++ b/composer.json @@ -48,9 +48,13 @@ "Shaarli\\Bookmark\\Exception\\": "application/bookmark/exception", "Shaarli\\Config\\": "application/config/", "Shaarli\\Config\\Exception\\": "application/config/exception", + "Shaarli\\Container\\": "application/container", "Shaarli\\Exceptions\\": "application/exceptions", "Shaarli\\Feed\\": "application/feed", "Shaarli\\Formatter\\": "application/formatter", + "Shaarli\\Front\\": "application/front", + "Shaarli\\Front\\Controller\\": "application/front/controllers", + "Shaarli\\Front\\Exception\\": "application/front/exceptions", "Shaarli\\Http\\": "application/http", "Shaarli\\Legacy\\": "application/legacy", "Shaarli\\Netscape\\": "application/netscape", diff --git a/doc/md/Translations.md b/doc/md/Translations.md index c7d33855..58b92da3 100644 --- a/doc/md/Translations.md +++ b/doc/md/Translations.md @@ -7,8 +7,8 @@ Note that only the `default` theme supports translations. ### Contributing -We encourage the community to contribute to Shaarli's translation either by improving existing -translations or submitting a new language. +We encourage the community to contribute to Shaarli's translation either by improving existing +translations or submitting a new language. Contributing to the translation does not require development skill. @@ -21,8 +21,8 @@ First, install [Poedit](https://poedit.net/) tool. Poedit will extract strings to translate from the PHP source code. -**Important**: due to the usage of a template engine, it's important to generate PHP cache files to extract -every translatable string. +**Important**: due to the usage of a template engine, it's important to generate PHP cache files to extract +every translatable string. You can either use [this script](https://gist.github.com/ArthurHoaro/5d0323f758ab2401ef444a53f54e9a07) (recommended) or visit every template page in your browser to generate cache files, while logged in. @@ -41,7 +41,7 @@ http:///?do=daily http:///?post http:///?do=export http:///?do=import -http:///?do=login +http:///login http:///?do=picwall http:///?do=pluginadmin http:///?do=tagcloud @@ -50,8 +50,8 @@ http:///?do=taglist #### Improve existing translation -In Poedit, click on "Edit a Translation", and from Shaarli's directory open -`inc/languages//LC_MESSAGES/shaarli.po`. +In Poedit, click on "Edit a Translation", and from Shaarli's directory open +`inc/languages//LC_MESSAGES/shaarli.po`. The existing list of translatable strings should have been loaded, then click on the "Update" button. @@ -63,20 +63,20 @@ Save when you're done, then you can submit a pull request containing the updated #### Add a new language -Open Poedit and select "Create New Translation", then from Shaarli's directory open +Open Poedit and select "Create New Translation", then from Shaarli's directory open `inc/languages//LC_MESSAGES/shaarli.po`. -Then select the language you want to create. +Then select the language you want to create. -Click on `File > Save as...`, and save your file in `/inc/language//LC_MESSAGES/shaarli.po`. -`` here should be the language code respecting the [ISO 3166-1 alpha-2](https://en.wikipedia.org/wiki/ISO_3166-2) +Click on `File > Save as...`, and save your file in `/inc/language//LC_MESSAGES/shaarli.po`. +`` here should be the language code respecting the [ISO 3166-1 alpha-2](https://en.wikipedia.org/wiki/ISO_3166-2) format in lowercase (e.g. `de` for German). Then click on the "Update" button, and you can start to translate every available string. Save when you're done, then you can submit a pull request containing the new `shaarli.po`. -### Theme translations +### Theme translations Theme translation extensions are loaded automatically if they're present. @@ -85,7 +85,7 @@ As a theme developer, all you have to do is to add the `.po` and `.mo` compiled tpl//language//LC_MESSAGES/.po tpl//language//LC_MESSAGES/.mo -Where `` is the ISO 3166-1 alpha-2 language code. +Where `` is the ISO 3166-1 alpha-2 language code. Read the following section "Extend Shaarli's translation" to learn how to generate those files. ### Extend Shaarli's translation @@ -106,7 +106,7 @@ First, create your translation files tree directory: Your `.po` files must be named like your domain. E.g. if your translation domain is `my_theme`, then your file will be `my_theme.po`. -Users have to register your extension in their configuration with the parameter +Users have to register your extension in their configuration with the parameter `translation.extensions.: `. Example: @@ -151,11 +151,11 @@ When you're done, open Poedit and load translation strings from sources: 1. `File > New` 2. Choose your language 3. Save your `PO` file in `/languages//LC_MESSAGES/my_theme.po`. - 4. Go to `Catalog > Properties...` + 4. Go to `Catalog > Properties...` 5. Fill the `Translation Properties` tab 6. Add your source path in the `Sources Paths` tab 7. In the `Sources Keywords` tab uncheck "Also use default keywords" and add the following lines: - + ``` my_theme_t my_theme_t:1,2 diff --git a/inc/languages/ja/LC_MESSAGES/shaarli.po b/inc/languages/ja/LC_MESSAGES/shaarli.po new file mode 100644 index 00000000..b420bb51 --- /dev/null +++ b/inc/languages/ja/LC_MESSAGES/shaarli.po @@ -0,0 +1,1293 @@ +msgid "" +msgstr "" +"Project-Id-Version: Shaarli\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2020-02-11 09:31+0900\n" +"PO-Revision-Date: 2020-02-11 10:54+0900\n" +"Last-Translator: yude \n" +"Language-Team: Shaarli\n" +"Language: ja\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: Poedit 2.3\n" +"X-Poedit-Basepath: ../../../..\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Poedit-SourceCharset: UTF-8\n" +"X-Poedit-KeywordsList: t:1,2;t\n" +"X-Poedit-SearchPath-0: .\n" +"X-Poedit-SearchPathExcluded-0: node_modules\n" +"X-Poedit-SearchPathExcluded-1: vendor\n" + +#: application/ApplicationUtils.php:153 +#, php-format +msgid "" +"Your PHP version is obsolete! Shaarli requires at least PHP %s, and thus " +"cannot run. Your PHP version has known security vulnerabilities and should " +"be updated as soon as possible." +msgstr "" +"使用している PHP のバージョンが古すぎます! Shaarli の実行には最低でも PHP %s " +"が必要です。 現在使用している PHP のバージョンには脆弱性があり、できるだけ速" +"やかにアップデートするべきです。" + +#: application/ApplicationUtils.php:183 application/ApplicationUtils.php:195 +msgid "directory is not readable" +msgstr "ディレクトリを読み込めません" + +#: application/ApplicationUtils.php:198 +msgid "directory is not writable" +msgstr "ディレクトリに書き込めません" + +#: application/ApplicationUtils.php:216 +msgid "file is not readable" +msgstr "ファイルを読み取る権限がありません" + +#: application/ApplicationUtils.php:219 +msgid "file is not writable" +msgstr "ファイルを書き込む権限がありません" + +#: application/Cache.php:16 +#, php-format +msgid "Cannot purge %s: no directory" +msgstr "%s を削除できません: ディレクトリが存在しません" + +#: application/FeedBuilder.php:151 +msgid "Direct link" +msgstr "ダイレクトリンク" + +#: application/FeedBuilder.php:153 +#: tmp/daily.b91ef64efc3688266305ea9b42e5017e.rtpl.php:88 +#: tmp/linklist.b91ef64efc3688266305ea9b42e5017e.rtpl.php:178 +msgid "Permalink" +msgstr "パーマリンク" + +#: application/History.php:174 +msgid "History file isn't readable or writable" +msgstr "履歴ファイルを読み込む、または書き込むための権限がありません" + +#: application/History.php:185 +msgid "Could not parse history file" +msgstr "履歴ファイルを正常に復元できませんでした" + +#: application/Languages.php:177 +msgid "Automatic" +msgstr "自動" + +#: application/Languages.php:178 +msgid "English" +msgstr "英語" + +#: application/Languages.php:179 +msgid "French" +msgstr "フランス語" + +#: application/Languages.php:180 +msgid "German" +msgstr "ドイツ語" + +#: application/LinkDB.php:136 +msgid "You are not authorized to add a link." +msgstr "リンクを追加するには、ログインする必要があります。" + +#: application/LinkDB.php:139 +msgid "Internal Error: A link should always have an id and URL." +msgstr "エラー: リンクにはIDとURLを登録しなければなりません。" + +#: application/LinkDB.php:142 +msgid "You must specify an integer as a key." +msgstr "正常なキーの値ではありません。" + +#: application/LinkDB.php:145 +msgid "Array offset and link ID must be equal." +msgstr "Array オフセットとリンクのIDは同じでなければなりません。" + +#: application/LinkDB.php:251 +#: tmp/page.footer.b91ef64efc3688266305ea9b42e5017e.rtpl.php:14 +#: tmp/page.footer.b91ef64efc3688266305ea9b42e5017e.rtpl.php:48 +#: tmp/page.footer.cedf684561d925457130839629000a81.rtpl.php:14 +#: tmp/page.footer.cedf684561d925457130839629000a81.rtpl.php:48 +msgid "" +"The personal, minimalist, super-fast, database free, bookmarking service" +msgstr "" +"個人向けの、ミニマムで高速でかつデータベースのいらないブックマークサービス" + +#: application/LinkDB.php:253 +msgid "" +"Welcome to Shaarli! This is your first public bookmark. To edit or delete " +"me, you must first login.\n" +"\n" +"To learn how to use Shaarli, consult the link \"Documentation\" at the " +"bottom of this page.\n" +"\n" +"You use the community supported version of the original Shaarli project, by " +"Sebastien Sauvage." +msgstr "" +"Shaarli へようこそ! これはあなたの最初の公開ブックマークです。これを編集した" +"り削除したりするには、ログインする必要があります。\n" +"\n" +"Shaarli の使い方を知るには、このページの下にある「ドキュメント」のリンクを開" +"いてください。\n" +"\n" +"あなたは Sebastien Sauvage による、コミュニティーサポートのあるバージョンのオ" +"リジナルのShaarli プロジェクトを使用しています。" + +#: application/LinkDB.php:267 +msgid "My secret stuff... - Pastebin.com" +msgstr "わたしのひ💗み💗つ💗 - Pastebin.com" + +#: application/LinkDB.php:269 +msgid "Shhhh! I'm a private link only YOU can see. You can delete me too." +msgstr "" +"シーッ! これはあなたしか見られないプライベートリンクです。消すこともできま" +"す。" + +#: application/LinkFilter.php:452 +msgid "The link you are trying to reach does not exist or has been deleted." +msgstr "開こうとしたリンクは存在しないか、削除されています。" + +#: application/NetscapeBookmarkUtils.php:35 +msgid "Invalid export selection:" +msgstr "不正なエクスポートの選択:" + +#: application/NetscapeBookmarkUtils.php:81 +#, php-format +msgid "File %s (%d bytes) " +msgstr "ファイル %s (%d バイト) " + +#: application/NetscapeBookmarkUtils.php:83 +msgid "has an unknown file format. Nothing was imported." +msgstr "は不明なファイル形式です。インポートは中止されました。" + +#: application/NetscapeBookmarkUtils.php:86 +#, php-format +msgid "" +"was successfully processed in %d seconds: %d links imported, %d links " +"overwritten, %d links skipped." +msgstr "" +"が %d 秒で処理され、%d 件のリンクがインポートされ、%d 件のリンクが上書きさ" +"れ、%d 件のリンクがスキップされました。" + +#: application/PageBuilder.php:168 +msgid "The page you are trying to reach does not exist or has been deleted." +msgstr "あなたが開こうとしたページは存在しないか、削除されています。" + +#: application/PageBuilder.php:170 +msgid "404 Not Found" +msgstr "404 ページが存在しません" + +#: application/PluginManager.php:243 +#, php-format +msgid "Plugin \"%s\" files not found." +msgstr "プラグイン「%s」のファイルが存在しません。" + +#: application/Updater.php:76 +msgid "Couldn't retrieve Updater class methods." +msgstr "アップデーターのクラスメゾットを受信できませんでした。" + +#: application/Updater.php:532 +msgid "An error occurred while running the update " +msgstr "更新中に問題が発生しました " + +#: application/Updater.php:572 +msgid "Updates file path is not set, can't write updates." +msgstr "更新するファイルのパスが指定されていないため、更新を書き込めません。" + +#: application/Updater.php:577 +msgid "Unable to write updates in " +msgstr "更新を次の項目に書き込めませんでした: " + +#: application/Utils.php:376 tests/UtilsTest.php:340 +msgid "Setting not set" +msgstr "未設定" + +#: application/Utils.php:383 tests/UtilsTest.php:338 tests/UtilsTest.php:339 +msgid "Unlimited" +msgstr "無制限" + +#: application/Utils.php:386 tests/UtilsTest.php:335 tests/UtilsTest.php:336 +#: tests/UtilsTest.php:350 +msgid "B" +msgstr "B" + +#: application/Utils.php:386 tests/UtilsTest.php:329 tests/UtilsTest.php:330 +#: tests/UtilsTest.php:337 +msgid "kiB" +msgstr "kiB" + +#: application/Utils.php:386 tests/UtilsTest.php:331 tests/UtilsTest.php:332 +#: tests/UtilsTest.php:348 tests/UtilsTest.php:349 +msgid "MiB" +msgstr "MiB" + +#: application/Utils.php:386 tests/UtilsTest.php:333 tests/UtilsTest.php:334 +msgid "GiB" +msgstr "GiB" + +#: application/config/ConfigJson.php:52 application/config/ConfigPhp.php:121 +msgid "" +"Shaarli could not create the config file. Please make sure Shaarli has the " +"right to write in the folder is it installed in." +msgstr "" +"Shaarli は設定ファイルを作成できませんでした。Shaarli が正しい権限下に置かれ" +"ていて、インストールされているディレクトリに書き込みできることを確認してくだ" +"さい。" + +#: application/config/ConfigManager.php:135 +msgid "Invalid setting key parameter. String expected, got: " +msgstr "" +"不正なキーの値です。文字列が想定されていますが、次のように入力されました: " + +#: application/config/exception/MissingFieldConfigException.php:21 +#, php-format +msgid "Configuration value is required for %s" +msgstr "%s には設定が必要です" + +#: application/config/exception/PluginConfigOrderException.php:15 +msgid "An error occurred while trying to save plugins loading order." +msgstr "プラグインの読込順を変更する際にエラーが発生しました。" + +#: application/config/exception/UnauthorizedConfigException.php:16 +msgid "You are not authorized to alter config." +msgstr "設定を変更する権限がありません。" + +#: application/exceptions/IOException.php:19 +msgid "Error accessing" +msgstr "読込中にエラーが発生しました" + +#: index.php:142 +msgid "Shared links on " +msgstr "次において共有されたリンク:" + +#: index.php:164 +msgid "Insufficient permissions:" +msgstr "権限がありません:" + +#: index.php:303 +msgid "I said: NO. You are banned for the moment. Go away." +msgstr "あなたはこのサーバーからBANされています。" + +#: index.php:368 +msgid "Wrong login/password." +msgstr "不正なユーザー名、またはパスワードです。" + +#: index.php:576 tmp/page.header.b91ef64efc3688266305ea9b42e5017e.rtpl.php:42 +#: tmp/page.header.cedf684561d925457130839629000a81.rtpl.php:42 +msgid "Daily" +msgstr "デイリー" + +#: index.php:681 tmp/loginform.b91ef64efc3688266305ea9b42e5017e.rtpl.php:28 +#: tmp/loginform.b91ef64efc3688266305ea9b42e5017e.rtpl.php:44 +#: tmp/page.header.b91ef64efc3688266305ea9b42e5017e.rtpl.php:71 +#: tmp/page.header.b91ef64efc3688266305ea9b42e5017e.rtpl.php:95 +#: tmp/page.header.cedf684561d925457130839629000a81.rtpl.php:71 +#: tmp/page.header.cedf684561d925457130839629000a81.rtpl.php:95 +msgid "Login" +msgstr "ログイン" + +#: index.php:722 tmp/page.header.b91ef64efc3688266305ea9b42e5017e.rtpl.php:39 +#: tmp/page.header.cedf684561d925457130839629000a81.rtpl.php:39 +msgid "Picture wall" +msgstr "ピクチャウォール" + +#: index.php:770 tmp/page.header.b91ef64efc3688266305ea9b42e5017e.rtpl.php:36 +#: tmp/page.header.cedf684561d925457130839629000a81.rtpl.php:36 +#: tmp/tag.cloud.b91ef64efc3688266305ea9b42e5017e.rtpl.php:19 +msgid "Tag cloud" +msgstr "タグクラウド" + +#: index.php:803 tmp/tag.list.b91ef64efc3688266305ea9b42e5017e.rtpl.php:19 +msgid "Tag list" +msgstr "タグ一覧" + +#: index.php:1028 tmp/page.header.b91ef64efc3688266305ea9b42e5017e.rtpl.php:31 +#: tmp/page.header.cedf684561d925457130839629000a81.rtpl.php:31 +msgid "Tools" +msgstr "ツール" + +#: index.php:1037 +msgid "You are not supposed to change a password on an Open Shaarli." +msgstr "" +"公開されている Shaarli において、パスワードを変更することは想定されていませ" +"ん。" + +#: index.php:1042 index.php:1084 index.php:1160 index.php:1191 index.php:1291 +msgid "Wrong token." +msgstr "不正なトークンです。" + +#: index.php:1047 +msgid "The old password is not correct." +msgstr "元のパスワードが正しくありません。" + +#: index.php:1067 +msgid "Your password has been changed" +msgstr "あなたのパスワードは変更されました" + +#: index.php:1072 +#: tmp/changepassword.b91ef64efc3688266305ea9b42e5017e.rtpl.php:13 +#: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:29 +msgid "Change password" +msgstr "パスワードを変更" + +#: index.php:1120 +msgid "Configuration was saved." +msgstr "設定は保存されました。" + +#: index.php:1143 tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:24 +msgid "Configure" +msgstr "設定" + +#: index.php:1154 tmp/changetag.b91ef64efc3688266305ea9b42e5017e.rtpl.php:13 +#: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:36 +msgid "Manage tags" +msgstr "タグを設定" + +#: index.php:1172 +#, php-format +msgid "The tag was removed from %d link." +msgid_plural "The tag was removed from %d links." +msgstr[0] "%d 件のリンクからタグが削除されました。" +msgstr[1] "The tag was removed from %d links." + +#: index.php:1173 +#, php-format +msgid "The tag was renamed in %d link." +msgid_plural "The tag was renamed in %d links." +msgstr[0] "タグが %d 件のリンクにおいて、名前が変更されました。" +msgstr[1] "タグが %d 件のリンクにおいて、名前が変更されました。" + +#: index.php:1181 tmp/addlink.b91ef64efc3688266305ea9b42e5017e.rtpl.php:13 +msgid "Shaare a new link" +msgstr "新しいリンクを追加" + +#: index.php:1351 tmp/editlink.b91ef64efc3688266305ea9b42e5017e.rtpl.php:14 +#: tmp/linklist.b91ef64efc3688266305ea9b42e5017e.rtpl.php:170 +msgid "Edit" +msgstr "共有" + +#: index.php:1351 index.php:1421 +#: tmp/editlink.b91ef64efc3688266305ea9b42e5017e.rtpl.php:16 +#: tmp/page.header.b91ef64efc3688266305ea9b42e5017e.rtpl.php:26 +#: tmp/page.header.cedf684561d925457130839629000a81.rtpl.php:26 +msgid "Shaare" +msgstr "Shaare" + +#: index.php:1390 +msgid "Note: " +msgstr "注: " + +#: index.php:1430 tmp/export.b91ef64efc3688266305ea9b42e5017e.rtpl.php:65 +msgid "Export" +msgstr "エクスポート" + +#: index.php:1492 tmp/import.b91ef64efc3688266305ea9b42e5017e.rtpl.php:83 +msgid "Import" +msgstr "インポート" + +#: index.php:1502 +#, php-format +msgid "" +"The file you are trying to upload is probably bigger than what this " +"webserver can accept (%s). Please upload in smaller chunks." +msgstr "" +"あなたがアップロードしようとしているファイルは、サーバーが許可しているファイ" +"ルサイズ (%s) よりも大きいです。もう少し小さいものをアップロードしてくださ" +"い。" + +#: index.php:1541 tmp/pluginsadmin.b91ef64efc3688266305ea9b42e5017e.rtpl.php:26 +#: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:22 +msgid "Plugin administration" +msgstr "プラグイン管理" + +#: index.php:1706 +msgid "Search: " +msgstr "検索: " + +#: index.php:1933 +#, php-format +msgid "" +"
Sessions do not seem to work correctly on your server.
Make sure the " +"variable \"session.save_path\" is set correctly in your PHP config, and that " +"you have write access to it.
It currently points to %s.
On some " +"browsers, accessing your server via a hostname like 'localhost' or any " +"custom hostname without a dot causes cookie storage to fail. We recommend " +"accessing your server via it's IP address or Fully Qualified Domain Name.
" +msgstr "" +"
セッションが正常にあなたのサーバー上で稼働していないようです。
PHP の" +"設定ファイル内にて、正しく \"session.save_path\" の値が設定されていることと、" +"権限が間違っていないことを確認してください。
現在 %s からPHPの設定ファイル" +"を読み込んでいます。
一部のブラウザーにおいて、localhost や他のドットを含" +"まないホスト名にてサーバーにアクセスする際に、クッキーを保存できないことがあ" +"ります。IP アドレスや完全なドメイン名でサーバーにアクセスすることをおすすめし" +"ます。
" + +#: index.php:1943 +msgid "Click to try again." +msgstr "クリックして再度試します。" + +#: plugins/addlink_toolbar/addlink_toolbar.php:29 +msgid "URI" +msgstr "URI" + +#: plugins/addlink_toolbar/addlink_toolbar.php:33 +#: tmp/addlink.b91ef64efc3688266305ea9b42e5017e.rtpl.php:19 +msgid "Add link" +msgstr "リンクを追加" + +#: plugins/addlink_toolbar/addlink_toolbar.php:50 +msgid "Adds the addlink input on the linklist page." +msgstr "リンク一覧のページに、リンクを追加するためのフォームを表示する。" + +#: plugins/archiveorg/archiveorg.php:23 +msgid "View on archive.org" +msgstr "archive.org 上で表示する" + +#: plugins/archiveorg/archiveorg.php:36 +msgid "For each link, add an Archive.org icon." +msgstr "それぞれのリンクに、Archive.org のアイコンを追加する。" + +#: plugins/demo_plugin/demo_plugin.php:465 +msgid "" +"A demo plugin covering all use cases for template designers and plugin " +"developers." +msgstr "" +"テンプレートのデザイナーや、プラグインの開発者のためのすべての状況に対応でき" +"るデモプラグインです。" + +#: plugins/isso/isso.php:20 +msgid "" +"Isso plugin error: Please define the \"ISSO_SERVER\" setting in the plugin " +"administration page." +msgstr "" +"Isso プラグインエラー: \"ISSO_SERVER\" の値をプラグイン管理ページにて指定して" +"ください。" + +#: plugins/isso/isso.php:63 +msgid "Let visitor comment your shaares on permalinks with Isso." +msgstr "" +"Isso を使って、あなたのパーマリンク上のリンクに第三者がコメントを残すことがで" +"きます。" + +#: plugins/isso/isso.php:64 +msgid "Isso server URL (without 'http://')" +msgstr "Isso server URL ('http://' 抜き)" + +#: plugins/markdown/markdown.php:158 +msgid "Description will be rendered with" +msgstr "説明は次の方法で描画されます:" + +#: plugins/markdown/markdown.php:159 +msgid "Markdown syntax documentation" +msgstr "マークダウン形式のドキュメント" + +#: plugins/markdown/markdown.php:160 +msgid "Markdown syntax" +msgstr "マークダウン形式" + +#: plugins/markdown/markdown.php:339 +msgid "" +"Render shaare description with Markdown syntax.
Warning:\n" +"If your shaared descriptions contained HTML tags before enabling the " +"markdown plugin,\n" +"enabling it might break your page.\n" +"See the README." +msgstr "" +"リンクの説明をマークダウン形式で表示します。
警告:\n" +"リンクの説明にHTMLタグがこのプラグインを有効にする前に含まれていた場合、\n" +"正常にページを表示できなくなるかもしれません。\n" +"詳しくは README をご覧ください。" + +#: plugins/piwik/piwik.php:21 +msgid "" +"Piwik plugin error: Please define PIWIK_URL and PIWIK_SITEID in the plugin " +"administration page." +msgstr "" +"Piwik プラグインエラー: PIWIK_URL と PIWIK_SITEID の値をプラグイン管理ページ" +"で指定してください。" + +#: plugins/piwik/piwik.php:70 +msgid "A plugin that adds Piwik tracking code to Shaarli pages." +msgstr "Piwik のトラッキングコードをShaarliに追加するプラグインです。" + +#: plugins/piwik/piwik.php:71 +msgid "Piwik URL" +msgstr "Piwik URL" + +#: plugins/piwik/piwik.php:72 +msgid "Piwik site ID" +msgstr "Piwik サイトID" + +#: plugins/playvideos/playvideos.php:22 +msgid "Video player" +msgstr "動画プレイヤー" + +#: plugins/playvideos/playvideos.php:25 +msgid "Play Videos" +msgstr "動画を再生" + +#: plugins/playvideos/playvideos.php:56 +msgid "Add a button in the toolbar allowing to watch all videos." +msgstr "すべての動画を閲覧するボタンをツールバーに追加します。" + +#: plugins/playvideos/youtube_playlist.js:214 +msgid "plugins/playvideos/jquery-1.11.2.min.js" +msgstr "plugins/playvideos/jquery-1.11.2.min.js" + +#: plugins/pubsubhubbub/pubsubhubbub.php:69 +#, php-format +msgid "Could not publish to PubSubHubbub: %s" +msgstr "PubSubHubbub に登録できませんでした: %s" + +#: plugins/pubsubhubbub/pubsubhubbub.php:95 +#, php-format +msgid "Could not post to %s" +msgstr "%s に登録できませんでした" + +#: plugins/pubsubhubbub/pubsubhubbub.php:99 +#, php-format +msgid "Bad response from the hub %s" +msgstr "ハブ %s からの不正なレスポンス" + +#: plugins/pubsubhubbub/pubsubhubbub.php:110 +msgid "Enable PubSubHubbub feed publishing." +msgstr "PubSubHubbub へのフィードを公開する。" + +#: plugins/qrcode/qrcode.php:69 plugins/wallabag/wallabag.php:68 +msgid "For each link, add a QRCode icon." +msgstr "それぞれのリンクについて、QRコードのアイコンを追加する。" + +#: plugins/wallabag/wallabag.php:21 +msgid "" +"Wallabag plugin error: Please define the \"WALLABAG_URL\" setting in the " +"plugin administration page." +msgstr "" +"Wallabag プラグインエラー: \"WALLABAG_URL\" の値をプラグイン管理ページにおい" +"て指定してください。" + +#: plugins/wallabag/wallabag.php:47 +msgid "Save to wallabag" +msgstr "Wallabag に保存" + +#: plugins/wallabag/wallabag.php:69 +msgid "Wallabag API URL" +msgstr "Wallabag のAPIのURL" + +#: plugins/wallabag/wallabag.php:70 +msgid "Wallabag API version (1 or 2)" +msgstr "Wallabag のAPIのバージョン (1 または 2)" + +#: tests/LanguagesTest.php:214 tests/LanguagesTest.php:227 +#: tests/languages/fr/LanguagesFrTest.php:160 +#: tests/languages/fr/LanguagesFrTest.php:173 +#: tmp/page.header.b91ef64efc3688266305ea9b42e5017e.rtpl.php:81 +#: tmp/page.header.cedf684561d925457130839629000a81.rtpl.php:81 +msgid "Search" +msgid_plural "Search" +msgstr[0] "検索" +msgstr[1] "検索" + +#: tmp/404.b91ef64efc3688266305ea9b42e5017e.rtpl.php:12 +msgid "Sorry, nothing to see here." +msgstr "すみませんが、ここには何もありません。" + +#: tmp/addlink.b91ef64efc3688266305ea9b42e5017e.rtpl.php:16 +msgid "URL or leave empty to post a note" +msgstr "URL を入力するか、空欄にするとノートを投稿します" + +#: tmp/changepassword.b91ef64efc3688266305ea9b42e5017e.rtpl.php:16 +msgid "Current password" +msgstr "現在のパスワード" + +#: tmp/changepassword.b91ef64efc3688266305ea9b42e5017e.rtpl.php:19 +msgid "New password" +msgstr "新しいパスワード" + +#: tmp/changepassword.b91ef64efc3688266305ea9b42e5017e.rtpl.php:23 +msgid "Change" +msgstr "変更" + +#: tmp/changetag.b91ef64efc3688266305ea9b42e5017e.rtpl.php:16 +#: tmp/import.b91ef64efc3688266305ea9b42e5017e.rtpl.php:77 +msgid "Tag" +msgstr "タグ" + +#: tmp/changetag.b91ef64efc3688266305ea9b42e5017e.rtpl.php:24 +msgid "New name" +msgstr "変更先の名前" + +#: tmp/changetag.b91ef64efc3688266305ea9b42e5017e.rtpl.php:31 +msgid "Case sensitive" +msgstr "大文字と小文字を区別" + +#: tmp/changetag.b91ef64efc3688266305ea9b42e5017e.rtpl.php:34 +msgid "Rename" +msgstr "名前を変更" + +#: tmp/changetag.b91ef64efc3688266305ea9b42e5017e.rtpl.php:35 +#: tmp/editlink.b91ef64efc3688266305ea9b42e5017e.rtpl.php:79 +#: tmp/linklist.b91ef64efc3688266305ea9b42e5017e.rtpl.php:172 +msgid "Delete" +msgstr "削除" + +#: tmp/changetag.b91ef64efc3688266305ea9b42e5017e.rtpl.php:39 +msgid "You can also edit tags in the" +msgstr "次に含まれるタグを編集することもできます:" + +#: tmp/changetag.b91ef64efc3688266305ea9b42e5017e.rtpl.php:39 +msgid "tag list" +msgstr "タグ一覧" + +#: tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:29 +msgid "title" +msgstr "タイトル" + +#: tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:43 +msgid "Home link" +msgstr "ホームのリンク先" + +#: tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:44 +msgid "Default value" +msgstr "既定の値" + +#: tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:58 +msgid "Theme" +msgstr "テーマ" + +#: tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:87 +#: tmp/install.b91ef64efc3688266305ea9b42e5017e.rtpl.php:78 +msgid "Language" +msgstr "言語" + +#: tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:116 +#: tmp/install.b91ef64efc3688266305ea9b42e5017e.rtpl.php:102 +msgid "Timezone" +msgstr "タイムゾーン" + +#: tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:117 +#: tmp/install.b91ef64efc3688266305ea9b42e5017e.rtpl.php:103 +msgid "Continent" +msgstr "大陸" + +#: tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:117 +#: tmp/install.b91ef64efc3688266305ea9b42e5017e.rtpl.php:103 +msgid "City" +msgstr "町" + +#: tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:164 +msgid "Disable session cookie hijacking protection" +msgstr "不正ログイン防止のためのセッションクッキーを無効化" + +#: tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:166 +msgid "Check this if you get disconnected or if your IP address changes often" +msgstr "" +"あなたが切断されたり、IPアドレスが頻繁に変わる環境下であるならチェックを入れ" +"てください" + +#: tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:183 +msgid "Private links by default" +msgstr "既定でプライベートリンク" + +#: tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:184 +msgid "All new links are private by default" +msgstr "すべての新規リンクをプライベートで作成" + +#: tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:199 +msgid "RSS direct links" +msgstr "RSS 直リンク" + +#: tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:200 +msgid "Check this to use direct URL instead of permalink in feeds" +msgstr "フィードでパーマリンクの代わりに直リンクを使う" + +#: tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:215 +msgid "Hide public links" +msgstr "公開リンクを隠す" + +#: tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:216 +msgid "Do not show any links if the user is not logged in" +msgstr "ログインしていないユーザーには何のリンクも表示しない" + +#: tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:231 +#: tmp/install.b91ef64efc3688266305ea9b42e5017e.rtpl.php:150 +msgid "Check updates" +msgstr "更新を確認" + +#: tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:232 +#: tmp/install.b91ef64efc3688266305ea9b42e5017e.rtpl.php:152 +msgid "Notify me when a new release is ready" +msgstr "新しいバージョンがリリースされたときに通知" + +#: tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:247 +#: tmp/install.b91ef64efc3688266305ea9b42e5017e.rtpl.php:169 +msgid "Enable REST API" +msgstr "REST API を有効化" + +#: tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:248 +#: tmp/install.b91ef64efc3688266305ea9b42e5017e.rtpl.php:170 +msgid "Allow third party software to use Shaarli such as mobile application" +msgstr "" +"モバイルアプリといったサードパーティーのソフトウェアにShaarliを使用することを" +"許可" + +#: tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:263 +msgid "API secret" +msgstr "API シークレット" + +#: tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:274 +#: tmp/editlink.b91ef64efc3688266305ea9b42e5017e.rtpl.php:74 +#: tmp/pluginsadmin.b91ef64efc3688266305ea9b42e5017e.rtpl.php:139 +#: tmp/pluginsadmin.b91ef64efc3688266305ea9b42e5017e.rtpl.php:199 +msgid "Save" +msgstr "保存" + +#: tmp/daily.b91ef64efc3688266305ea9b42e5017e.rtpl.php:15 +msgid "The Daily Shaarli" +msgstr "デイリーSharli" + +#: tmp/daily.b91ef64efc3688266305ea9b42e5017e.rtpl.php:17 +msgid "1 RSS entry per day" +msgstr "各日1つずつのRSS項目" + +#: tmp/daily.b91ef64efc3688266305ea9b42e5017e.rtpl.php:37 +msgid "Previous day" +msgstr "前日" + +#: tmp/daily.b91ef64efc3688266305ea9b42e5017e.rtpl.php:44 +msgid "All links of one day in a single page." +msgstr "1日に作成されたすべてのリンクです。" + +#: tmp/daily.b91ef64efc3688266305ea9b42e5017e.rtpl.php:51 +msgid "Next day" +msgstr "翌日" + +#: tmp/editlink.b91ef64efc3688266305ea9b42e5017e.rtpl.php:25 +msgid "Created:" +msgstr "作成:" + +#: tmp/editlink.b91ef64efc3688266305ea9b42e5017e.rtpl.php:28 +msgid "URL" +msgstr "URL" + +#: tmp/editlink.b91ef64efc3688266305ea9b42e5017e.rtpl.php:34 +msgid "Title" +msgstr "タイトル" + +#: tmp/editlink.b91ef64efc3688266305ea9b42e5017e.rtpl.php:40 +#: tmp/pluginsadmin.b91ef64efc3688266305ea9b42e5017e.rtpl.php:42 +#: tmp/pluginsadmin.b91ef64efc3688266305ea9b42e5017e.rtpl.php:75 +#: tmp/pluginsadmin.b91ef64efc3688266305ea9b42e5017e.rtpl.php:99 +#: tmp/pluginsadmin.b91ef64efc3688266305ea9b42e5017e.rtpl.php:124 +msgid "Description" +msgstr "説明" + +#: tmp/editlink.b91ef64efc3688266305ea9b42e5017e.rtpl.php:46 +msgid "Tags" +msgstr "タグ" + +#: tmp/editlink.b91ef64efc3688266305ea9b42e5017e.rtpl.php:59 +#: tmp/export.b91ef64efc3688266305ea9b42e5017e.rtpl.php:36 +#: tmp/linklist.b91ef64efc3688266305ea9b42e5017e.rtpl.php:168 +msgid "Private" +msgstr "プライベート" + +#: tmp/editlink.b91ef64efc3688266305ea9b42e5017e.rtpl.php:74 +msgid "Apply Changes" +msgstr "変更を適用" + +#: tmp/export.b91ef64efc3688266305ea9b42e5017e.rtpl.php:16 +msgid "Export Database" +msgstr "データベースをエクスポート" + +#: tmp/export.b91ef64efc3688266305ea9b42e5017e.rtpl.php:24 +msgid "Selection" +msgstr "選択済み" + +#: tmp/export.b91ef64efc3688266305ea9b42e5017e.rtpl.php:31 +msgid "All" +msgstr "すべて" + +#: tmp/export.b91ef64efc3688266305ea9b42e5017e.rtpl.php:41 +msgid "Public" +msgstr "公開" + +#: tmp/export.b91ef64efc3688266305ea9b42e5017e.rtpl.php:52 +msgid "Prepend note permalinks with this Shaarli instance's URL" +msgstr "この Shaarli のインスタンスのURL にノートへのパーマリンクを付け加える" + +#: tmp/export.b91ef64efc3688266305ea9b42e5017e.rtpl.php:53 +msgid "Useful to import bookmarks in a web browser" +msgstr "ウェブブラウザーのリンクをインポートするのに有効です" + +#: tmp/import.b91ef64efc3688266305ea9b42e5017e.rtpl.php:16 +msgid "Import Database" +msgstr "データベースをインポート" + +#: tmp/import.b91ef64efc3688266305ea9b42e5017e.rtpl.php:23 +msgid "Maximum size allowed:" +msgstr "最大サイズ:" + +#: tmp/import.b91ef64efc3688266305ea9b42e5017e.rtpl.php:29 +msgid "Visibility" +msgstr "可視性" + +#: tmp/import.b91ef64efc3688266305ea9b42e5017e.rtpl.php:36 +msgid "Use values from the imported file, default to public" +msgstr "インポート元のファイルの値を使用 (既定は公開リンクとなります)" + +#: tmp/import.b91ef64efc3688266305ea9b42e5017e.rtpl.php:41 +msgid "Import all bookmarks as private" +msgstr "すべてのブックマーク項目をプライベートリンクとしてインポート" + +#: tmp/import.b91ef64efc3688266305ea9b42e5017e.rtpl.php:46 +msgid "Import all bookmarks as public" +msgstr "すべてのブックマーク項目を公開リンクとしてインポート" + +#: tmp/import.b91ef64efc3688266305ea9b42e5017e.rtpl.php:57 +msgid "Overwrite existing bookmarks" +msgstr "既に存在しているブックマークを上書き" + +#: tmp/import.b91ef64efc3688266305ea9b42e5017e.rtpl.php:58 +msgid "Duplicates based on URL" +msgstr "URL による重複" + +#: tmp/import.b91ef64efc3688266305ea9b42e5017e.rtpl.php:72 +msgid "Add default tags" +msgstr "既定のタグを追加" + +#: tmp/install.b91ef64efc3688266305ea9b42e5017e.rtpl.php:22 +msgid "Install Shaarli" +msgstr "Shaarli をインストール" + +#: tmp/install.b91ef64efc3688266305ea9b42e5017e.rtpl.php:25 +msgid "It looks like it's the first time you run Shaarli. Please configure it." +msgstr "どうやら Shaarli を初めて起動しているようです。設定してください。" + +#: tmp/install.b91ef64efc3688266305ea9b42e5017e.rtpl.php:33 +#: tmp/loginform.b91ef64efc3688266305ea9b42e5017e.rtpl.php:30 +#: tmp/page.header.b91ef64efc3688266305ea9b42e5017e.rtpl.php:147 +#: tmp/page.header.cedf684561d925457130839629000a81.rtpl.php:147 +msgid "Username" +msgstr "ユーザー名" + +#: tmp/install.b91ef64efc3688266305ea9b42e5017e.rtpl.php:48 +#: tmp/loginform.b91ef64efc3688266305ea9b42e5017e.rtpl.php:34 +#: tmp/page.header.b91ef64efc3688266305ea9b42e5017e.rtpl.php:148 +#: tmp/page.header.cedf684561d925457130839629000a81.rtpl.php:148 +msgid "Password" +msgstr "パスワード" + +#: tmp/install.b91ef64efc3688266305ea9b42e5017e.rtpl.php:63 +msgid "Shaarli title" +msgstr "Shaarli のタイトル" + +#: tmp/install.b91ef64efc3688266305ea9b42e5017e.rtpl.php:69 +msgid "My links" +msgstr "自分のリンク" + +#: tmp/install.b91ef64efc3688266305ea9b42e5017e.rtpl.php:182 +msgid "Install" +msgstr "インストール" + +#: tmp/linklist.b91ef64efc3688266305ea9b42e5017e.rtpl.php:14 +#: tmp/linklist.b91ef64efc3688266305ea9b42e5017e.rtpl.php:80 +msgid "shaare" +msgid_plural "shaares" +msgstr[0] "共有" +msgstr[1] "共有" + +#: tmp/linklist.b91ef64efc3688266305ea9b42e5017e.rtpl.php:18 +#: tmp/linklist.b91ef64efc3688266305ea9b42e5017e.rtpl.php:84 +msgid "private link" +msgid_plural "private links" +msgstr[0] "プライベートリンク" +msgstr[1] "プライベートリンク" + +#: tmp/linklist.b91ef64efc3688266305ea9b42e5017e.rtpl.php:31 +#: tmp/page.header.b91ef64efc3688266305ea9b42e5017e.rtpl.php:117 +#: tmp/page.header.cedf684561d925457130839629000a81.rtpl.php:117 +msgid "Search text" +msgstr "文字列で検索" + +#: tmp/linklist.b91ef64efc3688266305ea9b42e5017e.rtpl.php:38 +#: tmp/page.header.b91ef64efc3688266305ea9b42e5017e.rtpl.php:124 +#: tmp/page.header.cedf684561d925457130839629000a81.rtpl.php:124 +#: tmp/tag.cloud.b91ef64efc3688266305ea9b42e5017e.rtpl.php:36 +#: tmp/tag.cloud.b91ef64efc3688266305ea9b42e5017e.rtpl.php:64 +#: tmp/tag.list.b91ef64efc3688266305ea9b42e5017e.rtpl.php:36 +#: tmp/tag.list.b91ef64efc3688266305ea9b42e5017e.rtpl.php:74 +msgid "Filter by tag" +msgstr "タグによって分類" + +#: tmp/linklist.b91ef64efc3688266305ea9b42e5017e.rtpl.php:111 +msgid "Nothing found." +msgstr "何も見つかりませんでした。" + +#: tmp/linklist.b91ef64efc3688266305ea9b42e5017e.rtpl.php:119 +#, php-format +msgid "%s result" +msgid_plural "%s results" +msgstr[0] "%s 件の結果" +msgstr[1] "%s 件の結果" + +#: tmp/linklist.b91ef64efc3688266305ea9b42e5017e.rtpl.php:123 +msgid "for" +msgstr "for" + +#: tmp/linklist.b91ef64efc3688266305ea9b42e5017e.rtpl.php:130 +msgid "tagged" +msgstr "タグ付けされた" + +#: tmp/linklist.b91ef64efc3688266305ea9b42e5017e.rtpl.php:134 +msgid "Remove tag" +msgstr "タグを削除" + +#: tmp/linklist.b91ef64efc3688266305ea9b42e5017e.rtpl.php:143 +msgid "with status" +msgstr "with status" + +#: tmp/linklist.b91ef64efc3688266305ea9b42e5017e.rtpl.php:154 +msgid "without any tag" +msgstr "タグなし" + +#: tmp/linklist.b91ef64efc3688266305ea9b42e5017e.rtpl.php:174 +#: tmp/page.footer.b91ef64efc3688266305ea9b42e5017e.rtpl.php:42 +#: tmp/page.footer.cedf684561d925457130839629000a81.rtpl.php:42 +msgid "Fold" +msgstr "畳む" + +#: tmp/linklist.b91ef64efc3688266305ea9b42e5017e.rtpl.php:176 +msgid "Edited: " +msgstr "編集済み: " + +#: tmp/linklist.b91ef64efc3688266305ea9b42e5017e.rtpl.php:180 +msgid "permalink" +msgstr "パーマリンク" + +#: tmp/linklist.b91ef64efc3688266305ea9b42e5017e.rtpl.php:182 +msgid "Add tag" +msgstr "タグを追加" + +#: tmp/linklist.paging.b91ef64efc3688266305ea9b42e5017e.rtpl.php:7 +#: tmp/linklist.paging.cedf684561d925457130839629000a81.rtpl.php:7 +msgid "Filters" +msgstr "分類" + +#: tmp/linklist.paging.b91ef64efc3688266305ea9b42e5017e.rtpl.php:12 +#: tmp/linklist.paging.cedf684561d925457130839629000a81.rtpl.php:12 +msgid "Only display private links" +msgstr "プライベートリンクのみを表示" + +#: tmp/linklist.paging.b91ef64efc3688266305ea9b42e5017e.rtpl.php:15 +#: tmp/linklist.paging.cedf684561d925457130839629000a81.rtpl.php:15 +msgid "Only display public links" +msgstr "公開リンクのみを表示" + +#: tmp/linklist.paging.b91ef64efc3688266305ea9b42e5017e.rtpl.php:20 +#: tmp/linklist.paging.cedf684561d925457130839629000a81.rtpl.php:20 +msgid "Filter untagged links" +msgstr "タグ付けされていないリンクで分類" + +#: tmp/linklist.paging.b91ef64efc3688266305ea9b42e5017e.rtpl.php:24 +#: tmp/linklist.paging.b91ef64efc3688266305ea9b42e5017e.rtpl.php:76 +#: tmp/linklist.paging.cedf684561d925457130839629000a81.rtpl.php:24 +#: tmp/linklist.paging.cedf684561d925457130839629000a81.rtpl.php:76 +#: tmp/page.footer.b91ef64efc3688266305ea9b42e5017e.rtpl.php:43 +#: tmp/page.footer.cedf684561d925457130839629000a81.rtpl.php:43 +msgid "Fold all" +msgstr "すべて畳む" + +#: tmp/linklist.paging.b91ef64efc3688266305ea9b42e5017e.rtpl.php:69 +#: tmp/linklist.paging.cedf684561d925457130839629000a81.rtpl.php:69 +msgid "Links per page" +msgstr "各ページをリンク" + +#: tmp/loginform.b91ef64efc3688266305ea9b42e5017e.rtpl.php:15 +msgid "" +"You have been banned after too many failed login attempts. Try again later." +msgstr "複数回に渡るログインへの失敗を検出しました。後でまた試してください。" + +#: tmp/loginform.b91ef64efc3688266305ea9b42e5017e.rtpl.php:41 +#: tmp/page.header.b91ef64efc3688266305ea9b42e5017e.rtpl.php:151 +#: tmp/page.header.cedf684561d925457130839629000a81.rtpl.php:151 +msgid "Remember me" +msgstr "パスワードを保存" + +#: tmp/page.footer.b91ef64efc3688266305ea9b42e5017e.rtpl.php:14 +#: tmp/page.footer.b91ef64efc3688266305ea9b42e5017e.rtpl.php:48 +#: tmp/page.footer.cedf684561d925457130839629000a81.rtpl.php:14 +#: tmp/page.footer.cedf684561d925457130839629000a81.rtpl.php:48 +msgid "by the Shaarli community" +msgstr "by Shaarli コミュニティ" + +#: tmp/page.footer.b91ef64efc3688266305ea9b42e5017e.rtpl.php:15 +#: tmp/page.footer.cedf684561d925457130839629000a81.rtpl.php:15 +msgid "Documentation" +msgstr "ドキュメント" + +#: tmp/page.footer.b91ef64efc3688266305ea9b42e5017e.rtpl.php:44 +#: tmp/page.footer.cedf684561d925457130839629000a81.rtpl.php:44 +msgid "Expand" +msgstr "展開する" + +#: tmp/page.footer.b91ef64efc3688266305ea9b42e5017e.rtpl.php:45 +#: tmp/page.footer.cedf684561d925457130839629000a81.rtpl.php:45 +msgid "Expand all" +msgstr "すべて展開する" + +#: tmp/page.footer.b91ef64efc3688266305ea9b42e5017e.rtpl.php:46 +#: tmp/page.footer.cedf684561d925457130839629000a81.rtpl.php:46 +msgid "Are you sure you want to delete this link?" +msgstr "本当にこのリンクを削除しますか?" + +#: tmp/page.header.b91ef64efc3688266305ea9b42e5017e.rtpl.php:61 +#: tmp/page.header.b91ef64efc3688266305ea9b42e5017e.rtpl.php:86 +#: tmp/page.header.cedf684561d925457130839629000a81.rtpl.php:61 +#: tmp/page.header.cedf684561d925457130839629000a81.rtpl.php:86 +msgid "RSS Feed" +msgstr "RSS フィード" + +#: tmp/page.header.b91ef64efc3688266305ea9b42e5017e.rtpl.php:66 +#: tmp/page.header.b91ef64efc3688266305ea9b42e5017e.rtpl.php:102 +#: tmp/page.header.cedf684561d925457130839629000a81.rtpl.php:66 +#: tmp/page.header.cedf684561d925457130839629000a81.rtpl.php:102 +msgid "Logout" +msgstr "ログアウト" + +#: tmp/page.header.b91ef64efc3688266305ea9b42e5017e.rtpl.php:169 +#: tmp/page.header.cedf684561d925457130839629000a81.rtpl.php:169 +msgid "is available" +msgstr "が利用可能" + +#: tmp/page.header.b91ef64efc3688266305ea9b42e5017e.rtpl.php:176 +#: tmp/page.header.cedf684561d925457130839629000a81.rtpl.php:176 +msgid "Error" +msgstr "エラー" + +#: tmp/picwall.b91ef64efc3688266305ea9b42e5017e.rtpl.php:16 +msgid "Picture Wall" +msgstr "ピクチャーウォール" + +#: tmp/picwall.b91ef64efc3688266305ea9b42e5017e.rtpl.php:16 +msgid "pics" +msgstr "画像" + +#: tmp/pluginsadmin.b91ef64efc3688266305ea9b42e5017e.rtpl.php:15 +msgid "You need to enable Javascript to change plugin loading order." +msgstr "" +"プラグインを読み込む順番を変更するには、Javascriptを有効にする必要がありま" +"す。" + +#: tmp/pluginsadmin.b91ef64efc3688266305ea9b42e5017e.rtpl.php:29 +msgid "Enabled Plugins" +msgstr "有効なプラグイン" + +#: tmp/pluginsadmin.b91ef64efc3688266305ea9b42e5017e.rtpl.php:34 +#: tmp/pluginsadmin.b91ef64efc3688266305ea9b42e5017e.rtpl.php:155 +msgid "No plugin enabled." +msgstr "有効なプラグインはありません。" + +#: tmp/pluginsadmin.b91ef64efc3688266305ea9b42e5017e.rtpl.php:40 +#: tmp/pluginsadmin.b91ef64efc3688266305ea9b42e5017e.rtpl.php:73 +msgid "Disable" +msgstr "無効化" + +#: tmp/pluginsadmin.b91ef64efc3688266305ea9b42e5017e.rtpl.php:41 +#: tmp/pluginsadmin.b91ef64efc3688266305ea9b42e5017e.rtpl.php:74 +#: tmp/pluginsadmin.b91ef64efc3688266305ea9b42e5017e.rtpl.php:98 +#: tmp/pluginsadmin.b91ef64efc3688266305ea9b42e5017e.rtpl.php:123 +msgid "Name" +msgstr "名前" + +#: tmp/pluginsadmin.b91ef64efc3688266305ea9b42e5017e.rtpl.php:43 +#: tmp/pluginsadmin.b91ef64efc3688266305ea9b42e5017e.rtpl.php:76 +msgid "Order" +msgstr "順序" + +#: tmp/pluginsadmin.b91ef64efc3688266305ea9b42e5017e.rtpl.php:86 +msgid "Disabled Plugins" +msgstr "無効なプラグイン" + +#: tmp/pluginsadmin.b91ef64efc3688266305ea9b42e5017e.rtpl.php:91 +msgid "No plugin disabled." +msgstr "無効なプラグインはありません。" + +#: tmp/pluginsadmin.b91ef64efc3688266305ea9b42e5017e.rtpl.php:97 +#: tmp/pluginsadmin.b91ef64efc3688266305ea9b42e5017e.rtpl.php:122 +msgid "Enable" +msgstr "有効化" + +#: tmp/pluginsadmin.b91ef64efc3688266305ea9b42e5017e.rtpl.php:134 +msgid "More plugins available" +msgstr "さらに利用できるプラグインがあります" + +#: tmp/pluginsadmin.b91ef64efc3688266305ea9b42e5017e.rtpl.php:136 +msgid "in the documentation" +msgstr "ドキュメント内" + +#: tmp/pluginsadmin.b91ef64efc3688266305ea9b42e5017e.rtpl.php:150 +msgid "Plugin configuration" +msgstr "プラグイン設定" + +#: tmp/pluginsadmin.b91ef64efc3688266305ea9b42e5017e.rtpl.php:195 +msgid "No parameter available." +msgstr "利用可能な設定項目はありません。" + +#: tmp/tag.cloud.b91ef64efc3688266305ea9b42e5017e.rtpl.php:19 +#: tmp/tag.list.b91ef64efc3688266305ea9b42e5017e.rtpl.php:19 +msgid "tags" +msgstr "タグ" + +#: tmp/tag.cloud.b91ef64efc3688266305ea9b42e5017e.rtpl.php:24 +#: tmp/tag.list.b91ef64efc3688266305ea9b42e5017e.rtpl.php:24 +msgid "List all links with those tags" +msgstr "このタグが付いているリンクをリスト化する" + +#: tmp/tag.sort.b91ef64efc3688266305ea9b42e5017e.rtpl.php:3 +#: tmp/tag.sort.cedf684561d925457130839629000a81.rtpl.php:3 +msgid "Sort by:" +msgstr "分類:" + +#: tmp/tag.sort.b91ef64efc3688266305ea9b42e5017e.rtpl.php:5 +#: tmp/tag.sort.cedf684561d925457130839629000a81.rtpl.php:5 +msgid "Cloud" +msgstr "クラウド" + +#: tmp/tag.sort.b91ef64efc3688266305ea9b42e5017e.rtpl.php:6 +#: tmp/tag.sort.cedf684561d925457130839629000a81.rtpl.php:6 +msgid "Most used" +msgstr "もっとも使われた" + +#: tmp/tag.sort.b91ef64efc3688266305ea9b42e5017e.rtpl.php:7 +#: tmp/tag.sort.cedf684561d925457130839629000a81.rtpl.php:7 +msgid "Alphabetical" +msgstr "アルファベット順" + +#: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:14 +msgid "Settings" +msgstr "設定" + +#: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:16 +msgid "Change Shaarli settings: title, timezone, etc." +msgstr "Shaarli の設定を変更: タイトル、タイムゾーンなど。" + +#: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:17 +msgid "Configure your Shaarli" +msgstr "あなたの Shaarli を設定" + +#: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:21 +msgid "Enable, disable and configure plugins" +msgstr "プラグインを有効化、無効化、設定する" + +#: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:28 +msgid "Change your password" +msgstr "パスワードを変更" + +#: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:35 +msgid "Rename or delete a tag in all links" +msgstr "すべてのリンクのタグの名前を変更する、または削除する" + +#: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:41 +msgid "" +"Import Netscape HTML bookmarks (as exported from Firefox, Chrome, Opera, " +"delicious...)" +msgstr "" +"Netscape HTML 形式のブックマークをインポートする (Firefox、Chrome、Operaと" +"いったブラウザーが含まれます)" + +#: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:42 +msgid "Import links" +msgstr "リンクをインポート" + +#: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:47 +msgid "" +"Export Netscape HTML bookmarks (which can be imported in Firefox, Chrome, " +"Opera, delicious...)" +msgstr "" +"Netscape HTML 形式のブックマークをエクスポートする (Firefox、Chrome、Operaと" +"いったブラウザーが含まれます)" + +#: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:48 +msgid "Export database" +msgstr "リンクをエクスポート" + +#: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:71 +msgid "" +"Drag one of these button to your bookmarks toolbar or right-click it and " +"\"Bookmark This Link\"" +msgstr "" +"これらのボタンのうち1つををブックマークバーにドラッグするか、右クリックして" +"「このリンクをブックマークに追加」してください" + +#: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:72 +msgid "then click on the bookmarklet in any page you want to share." +msgstr "共有したいページでブックマークレットをクリックしてください。" + +#: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:76 +#: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:100 +msgid "" +"Drag this link to your bookmarks toolbar or right-click it and Bookmark This " +"Link" +msgstr "" +"このリンクをブックマークバーにドラッグするか、右クリックして「このリンクを" +"ブックマークに追加」してください" + +#: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:77 +msgid "then click ✚Shaare link button in any page you want to share" +msgstr "✚リンクを共有 ボタンをクリックすることで、どこでもリンクを共有できます" + +#: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:86 +#: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:108 +msgid "The selected text is too long, it will be truncated." +msgstr "選択された文字列は長すぎるので、一部が切り捨てられます。" + +#: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:96 +msgid "Shaare link" +msgstr "共有リンク" + +#: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:101 +msgid "" +"Then click ✚Add Note button anytime to start composing a private Note (text " +"post) to your Shaarli" +msgstr "" +"✚ノートを追加 ボタンをクリックすることで、いつでもプライベートノート(テキスト" +"形式)をShaarli上に作成できます" + +#: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:117 +msgid "Add Note" +msgstr "ノートを追加" + +#: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:129 +msgid "" +"You need to browse your Shaarli over HTTPS to use this " +"functionality." +msgstr "" +"この機能を使用するには、HTTPS 経由でShaarliに接続してくださ" +"い。" + +#: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:134 +msgid "Add to" +msgstr "次に追加:" + +#: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:145 +msgid "3rd party" +msgstr "サードパーティー" + +#: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:147 +#: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:153 +msgid "Plugin" +msgstr "プラグイン" + +#: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:148 +#: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:154 +msgid "plugin" +msgstr "プラグイン" + +#: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:175 +msgid "" +"Drag this link to your bookmarks toolbar, or right-click it and choose " +"Bookmark This Link" +msgstr "" +"このリンクをブックマークバーにドラッグするか、右クリックして「このリンクを" +"ブックマークに追加」してください" diff --git a/index.php b/index.php index a39fc762..b53b16fe 100644 --- a/index.php +++ b/index.php @@ -61,29 +61,31 @@ require_once 'application/FileUtils.php'; require_once 'application/TimeZone.php'; require_once 'application/Utils.php'; -use \Shaarli\ApplicationUtils; -use Shaarli\Bookmark\BookmarkServiceInterface; -use \Shaarli\Bookmark\Exception\BookmarkNotFoundException; +use Shaarli\ApplicationUtils; use Shaarli\Bookmark\Bookmark; -use Shaarli\Bookmark\BookmarkFilter; use Shaarli\Bookmark\BookmarkFileService; -use \Shaarli\Config\ConfigManager; -use \Shaarli\Feed\CachedPage; -use \Shaarli\Feed\FeedBuilder; +use Shaarli\Bookmark\BookmarkFilter; +use Shaarli\Bookmark\BookmarkServiceInterface; +use Shaarli\Bookmark\Exception\BookmarkNotFoundException; +use Shaarli\Config\ConfigManager; +use Shaarli\Container\ContainerBuilder; +use Shaarli\Feed\CachedPage; +use Shaarli\Feed\FeedBuilder; use Shaarli\Formatter\BookmarkMarkdownFormatter; use Shaarli\Formatter\FormatterFactory; -use \Shaarli\History; -use \Shaarli\Languages; -use \Shaarli\Netscape\NetscapeBookmarkUtils; -use \Shaarli\Plugin\PluginManager; -use \Shaarli\Render\PageBuilder; -use \Shaarli\Render\ThemeUtils; -use \Shaarli\Router; -use \Shaarli\Security\LoginManager; -use \Shaarli\Security\SessionManager; -use \Shaarli\Thumbnailer; -use \Shaarli\Updater\Updater; -use \Shaarli\Updater\UpdaterUtils; +use Shaarli\History; +use Shaarli\Languages; +use Shaarli\Netscape\NetscapeBookmarkUtils; +use Shaarli\Plugin\PluginManager; +use Shaarli\Render\PageBuilder; +use Shaarli\Render\ThemeUtils; +use Shaarli\Router; +use Shaarli\Security\LoginManager; +use Shaarli\Security\SessionManager; +use Shaarli\Thumbnailer; +use Shaarli\Updater\Updater; +use Shaarli\Updater\UpdaterUtils; +use Slim\App; // Ensure the PHP version is supported try { @@ -243,12 +245,14 @@ if (isset($_POST['login'])) { } // Send cookie with the new expiration date to the browser + session_destroy(); session_set_cookie_params($expirationTime, $cookiedir, $_SERVER['SERVER_NAME']); + session_start(); session_regenerate_id(true); // Optional redirect after login: if (isset($_GET['post'])) { - $uri = '?post='. urlencode($_GET['post']); + $uri = './?post='. urlencode($_GET['post']); foreach (array('description', 'source', 'title', 'tags') as $param) { if (!empty($_GET[$param])) { $uri .= '&'.$param.'='.urlencode($_GET[$param]); @@ -259,22 +263,22 @@ if (isset($_POST['login'])) { } if (isset($_GET['edit_link'])) { - header('Location: ?edit_link='. escape($_GET['edit_link'])); + header('Location: ./?edit_link='. escape($_GET['edit_link'])); exit; } if (isset($_POST['returnurl'])) { // Prevent loops over login screen. - if (strpos($_POST['returnurl'], 'do=login') === false) { + if (strpos($_POST['returnurl'], '/login') === false) { header('Location: '. generateLocation($_POST['returnurl'], $_SERVER['HTTP_HOST'])); exit; } } - header('Location: ?'); + header('Location: ./?'); exit; } else { $loginManager->handleFailedLogin($_SERVER); - $redir = '&username='. urlencode($_POST['login']); + $redir = '?username='. urlencode($_POST['login']); if (isset($_GET['post'])) { $redir .= '&post=' . urlencode($_GET['post']); foreach (array('description', 'source', 'title', 'tags') as $param) { @@ -284,7 +288,7 @@ if (isset($_POST['login'])) { } } // Redirect to login screen. - echo ''; + echo ''; exit; } } @@ -592,19 +596,7 @@ function renderPage($conf, $pluginManager, $bookmarkService, $history, $sessionM // -------- Display login form. if ($targetPage == Router::$PAGE_LOGIN) { - if ($conf->get('security.open_shaarli')) { - header('Location: ?'); - exit; - } // No need to login for open Shaarli - if (isset($_GET['username'])) { - $PAGE->assign('username', escape($_GET['username'])); - } - $PAGE->assign('returnurl', (isset($_SERVER['HTTP_REFERER']) ? escape($_SERVER['HTTP_REFERER']):'')); - // add default state of the 'remember me' checkbox - $PAGE->assign('remember_user_default', $conf->get('privacy.remember_user_default')); - $PAGE->assign('user_can_login', $loginManager->canLogin($_SERVER)); - $PAGE->assign('pagetitle', t('Login') .' - '. $conf->get('general.title', 'Shaarli')); - $PAGE->renderPage('loginform'); + header('Location: ./login'); exit; } // -------- User wants to logout. @@ -667,6 +659,7 @@ function renderPage($conf, $pluginManager, $bookmarkService, $history, $sessionM alphabetical_sort($tags, false, true); + $logMaxCount = $maxcount > 1 ? log($maxcount, 30) : 1; $tagList = array(); foreach ($tags as $key => $value) { if (in_array($key, $filteringTags)) { @@ -674,8 +667,8 @@ function renderPage($conf, $pluginManager, $bookmarkService, $history, $sessionM } // Tag font size scaling: // default 15 and 30 logarithm bases affect scaling, - // 22 and 6 are arbitrary font sizes for max and min sizes. - $size = log($value, 15) / log($maxcount, 30) * 2.2 + 0.8; + // 2.2 and 0.8 are arbitrary font sizes in em. + $size = log($value, 15) / $logMaxCount * 2.2 + 0.8; $tagList[$key] = array( 'count' => $value, 'size' => number_format($size, 2, '.', ''), @@ -931,7 +924,7 @@ function renderPage($conf, $pluginManager, $bookmarkService, $history, $sessionM // Show login screen, then redirect to ?post=... if (isset($_GET['post'])) { header( // Redirect to login page, then back to post link. - 'Location: ?do=login&post='.urlencode($_GET['post']). + 'Location: /login?post='.urlencode($_GET['post']). (!empty($_GET['title'])?'&title='.urlencode($_GET['title']):''). (!empty($_GET['description'])?'&description='.urlencode($_GET['description']):''). (!empty($_GET['tags'])?'&tags='.urlencode($_GET['tags']):''). @@ -942,7 +935,7 @@ function renderPage($conf, $pluginManager, $bookmarkService, $history, $sessionM showLinkList($PAGE, $bookmarkService, $conf, $pluginManager, $loginManager); if (isset($_GET['edit_link'])) { - header('Location: ?do=login&edit_link='. escape($_GET['edit_link'])); + header('Location: /login?edit_link='. escape($_GET['edit_link'])); exit; } @@ -1898,7 +1891,7 @@ function install($conf, $sessionManager, $loginManager) echo ''; + .');document.location=\'./login\';'; exit; } @@ -1928,20 +1921,18 @@ if (isset($_SERVER['QUERY_STRING']) && startsWith($_SERVER['QUERY_STRING'], 'do= exit; } -$container = new \Slim\Container(); -$container['conf'] = $conf; -$container['plugins'] = $pluginManager; -$container['history'] = $history; -$app = new \Slim\App($container); +$containerBuilder = new ContainerBuilder($conf, $sessionManager, $loginManager); +$container = $containerBuilder->build(); +$app = new App($container); // REST API routes $app->group('/api/v1', function () { $this->get('/info', '\Shaarli\Api\Controllers\Info:getInfo')->setName('getInfo'); - $this->get('/bookmarks', '\Shaarli\Api\Controllers\Links:getLinks')->setName('getLinks'); - $this->get('/bookmarks/{id:[\d]+}', '\Shaarli\Api\Controllers\Links:getLink')->setName('getLink'); - $this->post('/bookmarks', '\Shaarli\Api\Controllers\Links:postLink')->setName('postLink'); - $this->put('/bookmarks/{id:[\d]+}', '\Shaarli\Api\Controllers\Links:putLink')->setName('putLink'); - $this->delete('/bookmarks/{id:[\d]+}', '\Shaarli\Api\Controllers\Links:deleteLink')->setName('deleteLink'); + $this->get('/links', '\Shaarli\Api\Controllers\Links:getLinks')->setName('getLinks'); + $this->get('/links/{id:[\d]+}', '\Shaarli\Api\Controllers\Links:getLink')->setName('getLink'); + $this->post('/links', '\Shaarli\Api\Controllers\Links:postLink')->setName('postLink'); + $this->put('/links/{id:[\d]+}', '\Shaarli\Api\Controllers\Links:putLink')->setName('putLink'); + $this->delete('/links/{id:[\d]+}', '\Shaarli\Api\Controllers\Links:deleteLink')->setName('deleteLink'); $this->get('/tags', '\Shaarli\Api\Controllers\Tags:getTags')->setName('getTags'); $this->get('/tags/{tagName:[\w]+}', '\Shaarli\Api\Controllers\Tags:getTag')->setName('getTag'); @@ -1951,6 +1942,10 @@ $app->group('/api/v1', function () { $this->get('/history', '\Shaarli\Api\Controllers\HistoryController:getHistory')->setName('getHistory'); })->add('\Shaarli\Api\ApiMiddleware'); +$app->group('', function () { + $this->get('/login', '\Shaarli\Front\Controller\LoginController:index')->setName('login'); +})->add('\Shaarli\Front\ShaarliMiddleware'); + $response = $app->run(true); // Hack to make Slim and Shaarli router work together: diff --git a/tests/UtilsTest.php b/tests/UtilsTest.php index 8225d95a..26d2a6b8 100644 --- a/tests/UtilsTest.php +++ b/tests/UtilsTest.php @@ -203,7 +203,7 @@ class UtilsTest extends PHPUnit\Framework\TestCase public function testGenerateLocationLoop() { $ref = 'http://localhost/?test'; - $this->assertEquals('?', generateLocation($ref, 'localhost', array('test'))); + $this->assertEquals('./?', generateLocation($ref, 'localhost', array('test'))); } /** @@ -212,7 +212,7 @@ class UtilsTest extends PHPUnit\Framework\TestCase public function testGenerateLocationOut() { $ref = 'http://somewebsite.com/?test'; - $this->assertEquals('?', generateLocation($ref, 'localhost')); + $this->assertEquals('./?', generateLocation($ref, 'localhost')); } diff --git a/tests/container/ContainerBuilderTest.php b/tests/container/ContainerBuilderTest.php new file mode 100644 index 00000000..9b97ed6d --- /dev/null +++ b/tests/container/ContainerBuilderTest.php @@ -0,0 +1,49 @@ +conf = new ConfigManager('tests/utils/config/configJson'); + $this->sessionManager = $this->createMock(SessionManager::class); + $this->loginManager = $this->createMock(LoginManager::class); + + $this->containerBuilder = new ContainerBuilder($this->conf, $this->sessionManager, $this->loginManager); + } + + public function testBuildContainer(): void + { + $container = $this->containerBuilder->build(); + + static::assertInstanceOf(ConfigManager::class, $container->conf); + static::assertInstanceOf(SessionManager::class, $container->sessionManager); + static::assertInstanceOf(LoginManager::class, $container->loginManager); + static::assertInstanceOf(History::class, $container->history); + static::assertInstanceOf(BookmarkServiceInterface::class, $container->bookmarkService); + static::assertInstanceOf(PageBuilder::class, $container->pageBuilder); + } +} diff --git a/tests/front/ShaarliMiddlewareTest.php b/tests/front/ShaarliMiddlewareTest.php new file mode 100644 index 00000000..80974f37 --- /dev/null +++ b/tests/front/ShaarliMiddlewareTest.php @@ -0,0 +1,70 @@ +container = $this->createMock(ShaarliContainer::class); + $this->middleware = new ShaarliMiddleware($this->container); + } + + public function testMiddlewareExecution(): void + { + $request = $this->createMock(Request::class); + $response = new Response(); + $controller = function (Request $request, Response $response): Response { + return $response->withStatus(418); // I'm a tea pot + }; + + /** @var Response $result */ + $result = $this->middleware->__invoke($request, $response, $controller); + + static::assertInstanceOf(Response::class, $result); + static::assertSame(418, $result->getStatusCode()); + } + + public function testMiddlewareExecutionWithException(): void + { + $request = $this->createMock(Request::class); + $response = new Response(); + $controller = function (): void { + $exception = new LoginBannedException(); + + throw new $exception; + }; + + $pageBuilder = $this->createMock(PageBuilder::class); + $pageBuilder->method('render')->willReturnCallback(function (string $message): string { + return $message; + }); + $this->container->pageBuilder = $pageBuilder; + + $conf = $this->createMock(ConfigManager::class); + $this->container->conf = $conf; + + /** @var Response $result */ + $result = $this->middleware->__invoke($request, $response, $controller); + + static::assertInstanceOf(Response::class, $result); + static::assertSame(401, $result->getStatusCode()); + static::assertContains('error', (string) $result->getBody()); + } +} diff --git a/tests/front/controller/LoginControllerTest.php b/tests/front/controller/LoginControllerTest.php new file mode 100644 index 00000000..8cf8ece7 --- /dev/null +++ b/tests/front/controller/LoginControllerTest.php @@ -0,0 +1,178 @@ +container = $this->createMock(ShaarliContainer::class); + $this->controller = new LoginController($this->container); + } + + public function testValidControllerInvoke(): void + { + $this->createValidContainerMockSet(); + + $request = $this->createMock(Request::class); + $request->expects(static::once())->method('getServerParam')->willReturn('> referer'); + $response = new Response(); + + $assignedVariables = []; + $this->container->pageBuilder + ->method('assign') + ->willReturnCallback(function ($key, $value) use (&$assignedVariables) { + $assignedVariables[$key] = $value; + + return $this; + }) + ; + + $result = $this->controller->index($request, $response); + + static::assertInstanceOf(Response::class, $result); + static::assertSame(200, $result->getStatusCode()); + static::assertSame('loginform', (string) $result->getBody()); + + static::assertSame('> referer', $assignedVariables['returnurl']); + static::assertSame(true, $assignedVariables['remember_user_default']); + static::assertSame('Login - Shaarli', $assignedVariables['pagetitle']); + } + + public function testValidControllerInvokeWithUserName(): void + { + $this->createValidContainerMockSet(); + + $request = $this->createMock(Request::class); + $request->expects(static::once())->method('getServerParam')->willReturn('> referer'); + $request->expects(static::exactly(2))->method('getParam')->willReturn('myUser>'); + $response = new Response(); + + $assignedVariables = []; + $this->container->pageBuilder + ->method('assign') + ->willReturnCallback(function ($key, $value) use (&$assignedVariables) { + $assignedVariables[$key] = $value; + + return $this; + }) + ; + + $result = $this->controller->index($request, $response); + + static::assertInstanceOf(Response::class, $result); + static::assertSame(200, $result->getStatusCode()); + static::assertSame('loginform', (string) $result->getBody()); + + static::assertSame('myUser>', $assignedVariables['username']); + static::assertSame('> referer', $assignedVariables['returnurl']); + static::assertSame(true, $assignedVariables['remember_user_default']); + static::assertSame('Login - Shaarli', $assignedVariables['pagetitle']); + } + + public function testLoginControllerWhileLoggedIn(): void + { + $request = $this->createMock(Request::class); + $response = new Response(); + + $loginManager = $this->createMock(LoginManager::class); + $loginManager->expects(static::once())->method('isLoggedIn')->willReturn(true); + $this->container->loginManager = $loginManager; + + $result = $this->controller->index($request, $response); + + static::assertInstanceOf(Response::class, $result); + static::assertSame(302, $result->getStatusCode()); + static::assertSame(['./'], $result->getHeader('Location')); + } + + public function testLoginControllerOpenShaarli(): void + { + $this->createValidContainerMockSet(); + + $request = $this->createMock(Request::class); + $response = new Response(); + + $conf = $this->createMock(ConfigManager::class); + $conf->method('get')->willReturnCallback(function (string $parameter, $default) { + if ($parameter === 'security.open_shaarli') { + return true; + } + return $default; + }); + $this->container->conf = $conf; + + $result = $this->controller->index($request, $response); + + static::assertInstanceOf(Response::class, $result); + static::assertSame(302, $result->getStatusCode()); + static::assertSame(['./'], $result->getHeader('Location')); + } + + public function testLoginControllerWhileBanned(): void + { + $this->createValidContainerMockSet(); + + $request = $this->createMock(Request::class); + $response = new Response(); + + $loginManager = $this->createMock(LoginManager::class); + $loginManager->method('isLoggedIn')->willReturn(false); + $loginManager->method('canLogin')->willReturn(false); + $this->container->loginManager = $loginManager; + + $this->expectException(LoginBannedException::class); + + $this->controller->index($request, $response); + } + + protected function createValidContainerMockSet(): void + { + // User logged out + $loginManager = $this->createMock(LoginManager::class); + $loginManager->method('isLoggedIn')->willReturn(false); + $loginManager->method('canLogin')->willReturn(true); + $this->container->loginManager = $loginManager; + + // Config + $conf = $this->createMock(ConfigManager::class); + $conf->method('get')->willReturnCallback(function (string $parameter, $default) { + return $default; + }); + $this->container->conf = $conf; + + // PageBuilder + $pageBuilder = $this->createMock(PageBuilder::class); + $pageBuilder + ->method('render') + ->willReturnCallback(function (string $template): string { + return $template; + }) + ; + $this->container->pageBuilder = $pageBuilder; + + $pluginManager = $this->createMock(PluginManager::class); + $this->container->pluginManager = $pluginManager; + $bookmarkService = $this->createMock(BookmarkServiceInterface::class); + $this->container->bookmarkService = $bookmarkService; + } +} diff --git a/tests/front/controller/ShaarliControllerTest.php b/tests/front/controller/ShaarliControllerTest.php new file mode 100644 index 00000000..6fa3feb9 --- /dev/null +++ b/tests/front/controller/ShaarliControllerTest.php @@ -0,0 +1,116 @@ +container = $this->createMock(ShaarliContainer::class); + $this->controller = new class($this->container) extends ShaarliController + { + public function assignView(string $key, $value): ShaarliController + { + return parent::assignView($key, $value); + } + + public function render(string $template): string + { + return parent::render($template); + } + }; + $this->assignedValues = []; + } + + public function testAssignView(): void + { + $this->createValidContainerMockSet(); + + $self = $this->controller->assignView('variableName', 'variableValue'); + + static::assertInstanceOf(ShaarliController::class, $self); + static::assertSame('variableValue', $this->assignedValues['variableName']); + } + + public function testRender(): void + { + $this->createValidContainerMockSet(); + + $render = $this->controller->render('templateName'); + + static::assertSame('templateName', $render); + + static::assertSame(10, $this->assignedValues['linkcount']); + static::assertSame(5, $this->assignedValues['privateLinkcount']); + static::assertSame(['error'], $this->assignedValues['plugin_errors']); + + static::assertSame('templateName', $this->assignedValues['plugins_includes']['render_includes']['target']); + static::assertTrue($this->assignedValues['plugins_includes']['render_includes']['loggedin']); + static::assertSame('templateName', $this->assignedValues['plugins_header']['render_header']['target']); + static::assertTrue($this->assignedValues['plugins_header']['render_header']['loggedin']); + static::assertSame('templateName', $this->assignedValues['plugins_footer']['render_footer']['target']); + static::assertTrue($this->assignedValues['plugins_footer']['render_footer']['loggedin']); + } + + protected function createValidContainerMockSet(): void + { + $pageBuilder = $this->createMock(PageBuilder::class); + $pageBuilder + ->method('assign') + ->willReturnCallback(function (string $key, $value): void { + $this->assignedValues[$key] = $value; + }); + $pageBuilder + ->method('render') + ->willReturnCallback(function (string $template): string { + return $template; + }); + $this->container->pageBuilder = $pageBuilder; + + $bookmarkService = $this->createMock(BookmarkServiceInterface::class); + $bookmarkService + ->method('count') + ->willReturnCallback(function (string $visibility): int { + return $visibility === BookmarkFilter::$PRIVATE ? 5 : 10; + }); + $this->container->bookmarkService = $bookmarkService; + + $pluginManager = $this->createMock(PluginManager::class); + $pluginManager + ->method('executeHooks') + ->willReturnCallback(function (string $hook, array &$data, array $params): array { + return $data[$hook] = $params; + }); + $pluginManager->method('getErrors')->willReturn(['error']); + $this->container->pluginManager = $pluginManager; + + $loginManager = $this->createMock(LoginManager::class); + $loginManager->method('isLoggedIn')->willReturn(true); + $this->container->loginManager = $loginManager; + } +} diff --git a/tpl/default/404.html b/tpl/default/404.html index 472566a6..09737b4b 100644 --- a/tpl/default/404.html +++ b/tpl/default/404.html @@ -6,7 +6,7 @@ - + {include="page.footer"}