diff options
31 files changed, 2235 insertions, 141 deletions
@@ -123,7 +123,8 @@ release_tar: composer_dependencies htmldoc translate build_frontend | |||
123 | ### generate a release zip and include 3rd-party dependencies and translations | 123 | ### generate a release zip and include 3rd-party dependencies and translations |
124 | release_zip: composer_dependencies htmldoc translate build_frontend | 124 | release_zip: composer_dependencies htmldoc translate build_frontend |
125 | git archive --prefix=$(ARCHIVE_PREFIX) -o $(ARCHIVE_VERSION).zip -9 HEAD | 125 | git archive --prefix=$(ARCHIVE_PREFIX) -o $(ARCHIVE_VERSION).zip -9 HEAD |
126 | mkdir -p $(ARCHIVE_PREFIX)/{doc,vendor} | 126 | mkdir -p $(ARCHIVE_PREFIX)/doc |
127 | mkdir -p $(ARCHIVE_PREFIX)/vendor | ||
127 | rsync -a doc/html/ $(ARCHIVE_PREFIX)doc/html/ | 128 | rsync -a doc/html/ $(ARCHIVE_PREFIX)doc/html/ |
128 | zip -r $(ARCHIVE_VERSION).zip $(ARCHIVE_PREFIX)doc/ | 129 | zip -r $(ARCHIVE_VERSION).zip $(ARCHIVE_PREFIX)doc/ |
129 | rsync -a vendor/ $(ARCHIVE_PREFIX)vendor/ | 130 | rsync -a vendor/ $(ARCHIVE_PREFIX)vendor/ |
@@ -155,6 +156,7 @@ phpdoc: clean | |||
155 | htmldoc: | 156 | htmldoc: |
156 | python3 -m venv venv/ | 157 | python3 -m venv venv/ |
157 | bash -c 'source venv/bin/activate; \ | 158 | bash -c 'source venv/bin/activate; \ |
159 | pip install wheel; \ | ||
158 | pip install mkdocs; \ | 160 | pip install mkdocs; \ |
159 | mkdocs build --clean' | 161 | mkdocs build --clean' |
160 | find doc/html/ -type f -exec chmod a-x '{}' \; | 162 | 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) | |||
159 | */ | 159 | */ |
160 | function generateLocation($referer, $host, $loopTerms = array()) | 160 | function generateLocation($referer, $host, $loopTerms = array()) |
161 | { | 161 | { |
162 | $finalReferer = '?'; | 162 | $finalReferer = './?'; |
163 | 163 | ||
164 | // No referer if it contains any value in $loopCriteria. | 164 | // No referer if it contains any value in $loopCriteria. |
165 | foreach (array_filter($loopTerms) as $value) { | 165 | 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 @@ | |||
1 | <?php | ||
2 | |||
3 | declare(strict_types=1); | ||
4 | |||
5 | namespace Shaarli\Container; | ||
6 | |||
7 | use Shaarli\Bookmark\BookmarkFileService; | ||
8 | use Shaarli\Bookmark\BookmarkServiceInterface; | ||
9 | use Shaarli\Config\ConfigManager; | ||
10 | use Shaarli\History; | ||
11 | use Shaarli\Plugin\PluginManager; | ||
12 | use Shaarli\Render\PageBuilder; | ||
13 | use Shaarli\Security\LoginManager; | ||
14 | use Shaarli\Security\SessionManager; | ||
15 | |||
16 | /** | ||
17 | * Class ContainerBuilder | ||
18 | * | ||
19 | * Helper used to build a Slim container instance with Shaarli's object dependencies. | ||
20 | * Note that most injected objects MUST be added as closures, to let the container instantiate | ||
21 | * only the objects it requires during the execution. | ||
22 | * | ||
23 | * @package Container | ||
24 | */ | ||
25 | class ContainerBuilder | ||
26 | { | ||
27 | /** @var ConfigManager */ | ||
28 | protected $conf; | ||
29 | |||
30 | /** @var SessionManager */ | ||
31 | protected $session; | ||
32 | |||
33 | /** @var LoginManager */ | ||
34 | protected $login; | ||
35 | |||
36 | public function __construct(ConfigManager $conf, SessionManager $session, LoginManager $login) | ||
37 | { | ||
38 | $this->conf = $conf; | ||
39 | $this->session = $session; | ||
40 | $this->login = $login; | ||
41 | } | ||
42 | |||
43 | public function build(): ShaarliContainer | ||
44 | { | ||
45 | $container = new ShaarliContainer(); | ||
46 | $container['conf'] = $this->conf; | ||
47 | $container['sessionManager'] = $this->session; | ||
48 | $container['loginManager'] = $this->login; | ||
49 | $container['plugins'] = function (ShaarliContainer $container): PluginManager { | ||
50 | return new PluginManager($container->conf); | ||
51 | }; | ||
52 | |||
53 | $container['history'] = function (ShaarliContainer $container): History { | ||
54 | return new History($container->conf->get('resource.history')); | ||
55 | }; | ||
56 | |||
57 | $container['bookmarkService'] = function (ShaarliContainer $container): BookmarkServiceInterface { | ||
58 | return new BookmarkFileService( | ||
59 | $container->conf, | ||
60 | $container->history, | ||
61 | $container->loginManager->isLoggedIn() | ||
62 | ); | ||
63 | }; | ||
64 | |||
65 | $container['pageBuilder'] = function (ShaarliContainer $container): PageBuilder { | ||
66 | return new PageBuilder( | ||
67 | $container->conf, | ||
68 | $container->sessionManager->getSession(), | ||
69 | $container->bookmarkService, | ||
70 | $container->sessionManager->generateToken(), | ||
71 | $container->loginManager->isLoggedIn() | ||
72 | ); | ||
73 | }; | ||
74 | |||
75 | $container['pluginManager'] = function (ShaarliContainer $container): PluginManager { | ||
76 | return new PluginManager($container->conf); | ||
77 | }; | ||
78 | |||
79 | return $container; | ||
80 | } | ||
81 | } | ||
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 @@ | |||
1 | <?php | ||
2 | |||
3 | declare(strict_types=1); | ||
4 | |||
5 | namespace Shaarli\Container; | ||
6 | |||
7 | use Shaarli\Bookmark\BookmarkServiceInterface; | ||
8 | use Shaarli\Config\ConfigManager; | ||
9 | use Shaarli\History; | ||
10 | use Shaarli\Plugin\PluginManager; | ||
11 | use Shaarli\Render\PageBuilder; | ||
12 | use Shaarli\Security\LoginManager; | ||
13 | use Shaarli\Security\SessionManager; | ||
14 | use Slim\Container; | ||
15 | |||
16 | /** | ||
17 | * Extension of Slim container to document the injected objects. | ||
18 | * | ||
19 | * @property ConfigManager $conf | ||
20 | * @property SessionManager $sessionManager | ||
21 | * @property LoginManager $loginManager | ||
22 | * @property History $history | ||
23 | * @property BookmarkServiceInterface $bookmarkService | ||
24 | * @property PageBuilder $pageBuilder | ||
25 | * @property PluginManager $pluginManager | ||
26 | */ | ||
27 | class ShaarliContainer extends Container | ||
28 | { | ||
29 | |||
30 | } | ||
diff --git a/application/front/ShaarliMiddleware.php b/application/front/ShaarliMiddleware.php new file mode 100644 index 00000000..fa6c6467 --- /dev/null +++ b/application/front/ShaarliMiddleware.php | |||
@@ -0,0 +1,57 @@ | |||
1 | <?php | ||
2 | |||
3 | namespace Shaarli\Front; | ||
4 | |||
5 | use Shaarli\Container\ShaarliContainer; | ||
6 | use Shaarli\Front\Exception\ShaarliException; | ||
7 | use Slim\Http\Request; | ||
8 | use Slim\Http\Response; | ||
9 | |||
10 | /** | ||
11 | * Class ShaarliMiddleware | ||
12 | * | ||
13 | * This will be called before accessing any Shaarli controller. | ||
14 | */ | ||
15 | class ShaarliMiddleware | ||
16 | { | ||
17 | /** @var ShaarliContainer contains all Shaarli DI */ | ||
18 | protected $container; | ||
19 | |||
20 | public function __construct(ShaarliContainer $container) | ||
21 | { | ||
22 | $this->container = $container; | ||
23 | } | ||
24 | |||
25 | /** | ||
26 | * Middleware execution: | ||
27 | * - execute the controller | ||
28 | * - return the response | ||
29 | * | ||
30 | * In case of error, the error template will be displayed with the exception message. | ||
31 | * | ||
32 | * @param Request $request Slim request | ||
33 | * @param Response $response Slim response | ||
34 | * @param callable $next Next action | ||
35 | * | ||
36 | * @return Response response. | ||
37 | */ | ||
38 | public function __invoke(Request $request, Response $response, callable $next) | ||
39 | { | ||
40 | try { | ||
41 | $response = $next($request, $response); | ||
42 | } catch (ShaarliException $e) { | ||
43 | $this->container->pageBuilder->assign('message', $e->getMessage()); | ||
44 | if ($this->container->conf->get('dev.debug', false)) { | ||
45 | $this->container->pageBuilder->assign( | ||
46 | 'stacktrace', | ||
47 | nl2br(get_class($this) .': '. $e->getTraceAsString()) | ||
48 | ); | ||
49 | } | ||
50 | |||
51 | $response = $response->withStatus($e->getCode()); | ||
52 | $response = $response->write($this->container->pageBuilder->render('error')); | ||
53 | } | ||
54 | |||
55 | return $response; | ||
56 | } | ||
57 | } | ||
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 @@ | |||
1 | <?php | ||
2 | |||
3 | declare(strict_types=1); | ||
4 | |||
5 | namespace Shaarli\Front\Controller; | ||
6 | |||
7 | use Shaarli\Front\Exception\LoginBannedException; | ||
8 | use Slim\Http\Request; | ||
9 | use Slim\Http\Response; | ||
10 | |||
11 | /** | ||
12 | * Class LoginController | ||
13 | * | ||
14 | * Slim controller used to render the login page. | ||
15 | * | ||
16 | * The login page is not available if the user is banned | ||
17 | * or if open shaarli setting is enabled. | ||
18 | * | ||
19 | * @package Front\Controller | ||
20 | */ | ||
21 | class LoginController extends ShaarliController | ||
22 | { | ||
23 | public function index(Request $request, Response $response): Response | ||
24 | { | ||
25 | if ($this->container->loginManager->isLoggedIn() | ||
26 | || $this->container->conf->get('security.open_shaarli', false) | ||
27 | ) { | ||
28 | return $response->withRedirect('./'); | ||
29 | } | ||
30 | |||
31 | $userCanLogin = $this->container->loginManager->canLogin($request->getServerParams()); | ||
32 | if ($userCanLogin !== true) { | ||
33 | throw new LoginBannedException(); | ||
34 | } | ||
35 | |||
36 | if ($request->getParam('username') !== null) { | ||
37 | $this->assignView('username', escape($request->getParam('username'))); | ||
38 | } | ||
39 | |||
40 | $this | ||
41 | ->assignView('returnurl', escape($request->getServerParam('HTTP_REFERER'))) | ||
42 | ->assignView('remember_user_default', $this->container->conf->get('privacy.remember_user_default', true)) | ||
43 | ->assignView('pagetitle', t('Login') .' - '. $this->container->conf->get('general.title', 'Shaarli')) | ||
44 | ; | ||
45 | |||
46 | return $response->write($this->render('loginform')); | ||
47 | } | ||
48 | } | ||
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 @@ | |||
1 | <?php | ||
2 | |||
3 | declare(strict_types=1); | ||
4 | |||
5 | namespace Shaarli\Front\Controller; | ||
6 | |||
7 | use Shaarli\Bookmark\BookmarkFilter; | ||
8 | use Shaarli\Container\ShaarliContainer; | ||
9 | |||
10 | abstract class ShaarliController | ||
11 | { | ||
12 | /** @var ShaarliContainer */ | ||
13 | protected $container; | ||
14 | |||
15 | /** @param ShaarliContainer $container Slim container (extended for attribute completion). */ | ||
16 | public function __construct(ShaarliContainer $container) | ||
17 | { | ||
18 | $this->container = $container; | ||
19 | } | ||
20 | |||
21 | /** | ||
22 | * Assign variables to RainTPL template through the PageBuilder. | ||
23 | * | ||
24 | * @param mixed $value Value to assign to the template | ||
25 | */ | ||
26 | protected function assignView(string $name, $value): self | ||
27 | { | ||
28 | $this->container->pageBuilder->assign($name, $value); | ||
29 | |||
30 | return $this; | ||
31 | } | ||
32 | |||
33 | protected function render(string $template): string | ||
34 | { | ||
35 | $this->assignView('linkcount', $this->container->bookmarkService->count(BookmarkFilter::$ALL)); | ||
36 | $this->assignView('privateLinkcount', $this->container->bookmarkService->count(BookmarkFilter::$PRIVATE)); | ||
37 | $this->assignView('plugin_errors', $this->container->pluginManager->getErrors()); | ||
38 | |||
39 | $this->executeDefaultHooks($template); | ||
40 | |||
41 | return $this->container->pageBuilder->render($template); | ||
42 | } | ||
43 | |||
44 | /** | ||
45 | * Call plugin hooks for header, footer and includes, specifying which page will be rendered. | ||
46 | * Then assign generated data to RainTPL. | ||
47 | */ | ||
48 | protected function executeDefaultHooks(string $template): void | ||
49 | { | ||
50 | $common_hooks = [ | ||
51 | 'includes', | ||
52 | 'header', | ||
53 | 'footer', | ||
54 | ]; | ||
55 | |||
56 | foreach ($common_hooks as $name) { | ||
57 | $plugin_data = []; | ||
58 | $this->container->pluginManager->executeHooks( | ||
59 | 'render_' . $name, | ||
60 | $plugin_data, | ||
61 | [ | ||
62 | 'target' => $template, | ||
63 | 'loggedin' => $this->container->loginManager->isLoggedIn() | ||
64 | ] | ||
65 | ); | ||
66 | $this->assignView('plugins_' . $name, $plugin_data); | ||
67 | } | ||
68 | } | ||
69 | } | ||
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 @@ | |||
1 | <?php | ||
2 | |||
3 | declare(strict_types=1); | ||
4 | |||
5 | namespace Shaarli\Front\Exception; | ||
6 | |||
7 | class LoginBannedException extends ShaarliException | ||
8 | { | ||
9 | public function __construct() | ||
10 | { | ||
11 | $message = t('You have been banned after too many failed login attempts. Try again later.'); | ||
12 | |||
13 | parent::__construct($message, 401); | ||
14 | } | ||
15 | } | ||
diff --git a/application/front/exceptions/ShaarliException.php b/application/front/exceptions/ShaarliException.php new file mode 100644 index 00000000..800bfbec --- /dev/null +++ b/application/front/exceptions/ShaarliException.php | |||
@@ -0,0 +1,23 @@ | |||
1 | <?php | ||
2 | |||
3 | declare(strict_types=1); | ||
4 | |||
5 | namespace Shaarli\Front\Exception; | ||
6 | |||
7 | use Throwable; | ||
8 | |||
9 | /** | ||
10 | * Class ShaarliException | ||
11 | * | ||
12 | * Abstract exception class used to defined any custom exception thrown during front rendering. | ||
13 | * | ||
14 | * @package Front\Exception | ||
15 | */ | ||
16 | abstract class ShaarliException extends \Exception | ||
17 | { | ||
18 | /** Override parent constructor to force $message and $httpCode parameters to be set. */ | ||
19 | public function __construct(string $message, int $httpCode, Throwable $previous = null) | ||
20 | { | ||
21 | parent::__construct($message, $httpCode, $previous); | ||
22 | } | ||
23 | } | ||
diff --git a/application/render/PageBuilder.php b/application/render/PageBuilder.php index 65e85aaf..f4fefda8 100644 --- a/application/render/PageBuilder.php +++ b/application/render/PageBuilder.php | |||
@@ -200,6 +200,23 @@ class PageBuilder | |||
200 | } | 200 | } |
201 | 201 | ||
202 | /** | 202 | /** |
203 | * Render a specific page as string (using a template file). | ||
204 | * e.g. $pb->render('picwall'); | ||
205 | * | ||
206 | * @param string $page Template filename (without extension). | ||
207 | * | ||
208 | * @return string Processed template content | ||
209 | */ | ||
210 | public function render(string $page): string | ||
211 | { | ||
212 | if ($this->tpl === false) { | ||
213 | $this->initialize(); | ||
214 | } | ||
215 | |||
216 | return $this->tpl->draw($page, true); | ||
217 | } | ||
218 | |||
219 | /** | ||
203 | * Render a 404 page (uses the template : tpl/404.tpl) | 220 | * Render a 404 page (uses the template : tpl/404.tpl) |
204 | * usage: $PAGE->render404('The link was deleted') | 221 | * usage: $PAGE->render404('The link was deleted') |
205 | * | 222 | * |
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 | |||
196 | } | 196 | } |
197 | return true; | 197 | return true; |
198 | } | 198 | } |
199 | |||
200 | /** @return array Local reference to the global $_SESSION array */ | ||
201 | public function getSession(): array | ||
202 | { | ||
203 | return $this->session; | ||
204 | } | ||
199 | } | 205 | } |
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 { | |||
1236 | color: $dark-grey; | 1236 | color: $dark-grey; |
1237 | } | 1237 | } |
1238 | 1238 | ||
1239 | .page404-container { | 1239 | .page-error-container { |
1240 | color: $dark-grey; | 1240 | color: $dark-grey; |
1241 | |||
1242 | h2 { | ||
1243 | margin: 70px 0 25px; | ||
1244 | } | ||
1245 | |||
1246 | pre { | ||
1247 | margin: 0 20%; | ||
1248 | padding: 20px 0; | ||
1249 | text-align: left; | ||
1250 | line-height: .7em; | ||
1251 | } | ||
1241 | } | 1252 | } |
1242 | 1253 | ||
1243 | // EDIT LINK | 1254 | // EDIT LINK |
diff --git a/composer.json b/composer.json index ada06a74..6b670fa2 100644 --- a/composer.json +++ b/composer.json | |||
@@ -48,9 +48,13 @@ | |||
48 | "Shaarli\\Bookmark\\Exception\\": "application/bookmark/exception", | 48 | "Shaarli\\Bookmark\\Exception\\": "application/bookmark/exception", |
49 | "Shaarli\\Config\\": "application/config/", | 49 | "Shaarli\\Config\\": "application/config/", |
50 | "Shaarli\\Config\\Exception\\": "application/config/exception", | 50 | "Shaarli\\Config\\Exception\\": "application/config/exception", |
51 | "Shaarli\\Container\\": "application/container", | ||
51 | "Shaarli\\Exceptions\\": "application/exceptions", | 52 | "Shaarli\\Exceptions\\": "application/exceptions", |
52 | "Shaarli\\Feed\\": "application/feed", | 53 | "Shaarli\\Feed\\": "application/feed", |
53 | "Shaarli\\Formatter\\": "application/formatter", | 54 | "Shaarli\\Formatter\\": "application/formatter", |
55 | "Shaarli\\Front\\": "application/front", | ||
56 | "Shaarli\\Front\\Controller\\": "application/front/controllers", | ||
57 | "Shaarli\\Front\\Exception\\": "application/front/exceptions", | ||
54 | "Shaarli\\Http\\": "application/http", | 58 | "Shaarli\\Http\\": "application/http", |
55 | "Shaarli\\Legacy\\": "application/legacy", | 59 | "Shaarli\\Legacy\\": "application/legacy", |
56 | "Shaarli\\Netscape\\": "application/netscape", | 60 | "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. | |||
7 | 7 | ||
8 | ### Contributing | 8 | ### Contributing |
9 | 9 | ||
10 | We encourage the community to contribute to Shaarli's translation either by improving existing | 10 | We encourage the community to contribute to Shaarli's translation either by improving existing |
11 | translations or submitting a new language. | 11 | translations or submitting a new language. |
12 | 12 | ||
13 | Contributing to the translation does not require development skill. | 13 | Contributing to the translation does not require development skill. |
14 | 14 | ||
@@ -21,8 +21,8 @@ First, install [Poedit](https://poedit.net/) tool. | |||
21 | 21 | ||
22 | Poedit will extract strings to translate from the PHP source code. | 22 | Poedit will extract strings to translate from the PHP source code. |
23 | 23 | ||
24 | **Important**: due to the usage of a template engine, it's important to generate PHP cache files to extract | 24 | **Important**: due to the usage of a template engine, it's important to generate PHP cache files to extract |
25 | every translatable string. | 25 | every translatable string. |
26 | 26 | ||
27 | You can either use [this script](https://gist.github.com/ArthurHoaro/5d0323f758ab2401ef444a53f54e9a07) (recommended) | 27 | You can either use [this script](https://gist.github.com/ArthurHoaro/5d0323f758ab2401ef444a53f54e9a07) (recommended) |
28 | or visit every template page in your browser to generate cache files, while logged in. | 28 | or visit every template page in your browser to generate cache files, while logged in. |
@@ -41,7 +41,7 @@ http://<replace_domain>/?do=daily | |||
41 | http://<replace_domain>/?post | 41 | http://<replace_domain>/?post |
42 | http://<replace_domain>/?do=export | 42 | http://<replace_domain>/?do=export |
43 | http://<replace_domain>/?do=import | 43 | http://<replace_domain>/?do=import |
44 | http://<replace_domain>/?do=login | 44 | http://<replace_domain>/login |
45 | http://<replace_domain>/?do=picwall | 45 | http://<replace_domain>/?do=picwall |
46 | http://<replace_domain>/?do=pluginadmin | 46 | http://<replace_domain>/?do=pluginadmin |
47 | http://<replace_domain>/?do=tagcloud | 47 | http://<replace_domain>/?do=tagcloud |
@@ -50,8 +50,8 @@ http://<replace_domain>/?do=taglist | |||
50 | 50 | ||
51 | #### Improve existing translation | 51 | #### Improve existing translation |
52 | 52 | ||
53 | In Poedit, click on "Edit a Translation", and from Shaarli's directory open | 53 | In Poedit, click on "Edit a Translation", and from Shaarli's directory open |
54 | `inc/languages/<lang>/LC_MESSAGES/shaarli.po`. | 54 | `inc/languages/<lang>/LC_MESSAGES/shaarli.po`. |
55 | 55 | ||
56 | The existing list of translatable strings should have been loaded, then click on the "Update" button. | 56 | The existing list of translatable strings should have been loaded, then click on the "Update" button. |
57 | 57 | ||
@@ -63,20 +63,20 @@ Save when you're done, then you can submit a pull request containing the updated | |||
63 | 63 | ||
64 | #### Add a new language | 64 | #### Add a new language |
65 | 65 | ||
66 | Open Poedit and select "Create New Translation", then from Shaarli's directory open | 66 | Open Poedit and select "Create New Translation", then from Shaarli's directory open |
67 | `inc/languages/<lang>/LC_MESSAGES/shaarli.po`. | 67 | `inc/languages/<lang>/LC_MESSAGES/shaarli.po`. |
68 | 68 | ||
69 | Then select the language you want to create. | 69 | Then select the language you want to create. |
70 | 70 | ||
71 | Click on `File > Save as...`, and save your file in `<shaarli directory>/inc/language/<new language>/LC_MESSAGES/shaarli.po`. | 71 | Click on `File > Save as...`, and save your file in `<shaarli directory>/inc/language/<new language>/LC_MESSAGES/shaarli.po`. |
72 | `<new language>` here should be the language code respecting the [ISO 3166-1 alpha-2](https://en.wikipedia.org/wiki/ISO_3166-2) | 72 | `<new language>` here should be the language code respecting the [ISO 3166-1 alpha-2](https://en.wikipedia.org/wiki/ISO_3166-2) |
73 | format in lowercase (e.g. `de` for German). | 73 | format in lowercase (e.g. `de` for German). |
74 | 74 | ||
75 | Then click on the "Update" button, and you can start to translate every available string. | 75 | Then click on the "Update" button, and you can start to translate every available string. |
76 | 76 | ||
77 | Save when you're done, then you can submit a pull request containing the new `shaarli.po`. | 77 | Save when you're done, then you can submit a pull request containing the new `shaarli.po`. |
78 | 78 | ||
79 | ### Theme translations | 79 | ### Theme translations |
80 | 80 | ||
81 | Theme translation extensions are loaded automatically if they're present. | 81 | Theme translation extensions are loaded automatically if they're present. |
82 | 82 | ||
@@ -85,7 +85,7 @@ As a theme developer, all you have to do is to add the `.po` and `.mo` compiled | |||
85 | tpl/<theme name>/language/<lang>/LC_MESSAGES/<theme name>.po | 85 | tpl/<theme name>/language/<lang>/LC_MESSAGES/<theme name>.po |
86 | tpl/<theme name>/language/<lang>/LC_MESSAGES/<theme name>.mo | 86 | tpl/<theme name>/language/<lang>/LC_MESSAGES/<theme name>.mo |
87 | 87 | ||
88 | Where `<lang>` is the ISO 3166-1 alpha-2 language code. | 88 | Where `<lang>` is the ISO 3166-1 alpha-2 language code. |
89 | Read the following section "Extend Shaarli's translation" to learn how to generate those files. | 89 | Read the following section "Extend Shaarli's translation" to learn how to generate those files. |
90 | 90 | ||
91 | ### Extend Shaarli's translation | 91 | ### Extend Shaarli's translation |
@@ -106,7 +106,7 @@ First, create your translation files tree directory: | |||
106 | Your `.po` files must be named like your domain. E.g. if your translation domain is `my_theme`, then your file will be | 106 | Your `.po` files must be named like your domain. E.g. if your translation domain is `my_theme`, then your file will be |
107 | `my_theme.po`. | 107 | `my_theme.po`. |
108 | 108 | ||
109 | Users have to register your extension in their configuration with the parameter | 109 | Users have to register your extension in their configuration with the parameter |
110 | `translation.extensions.<domain>: <translation files path>`. | 110 | `translation.extensions.<domain>: <translation files path>`. |
111 | 111 | ||
112 | Example: | 112 | Example: |
@@ -151,11 +151,11 @@ When you're done, open Poedit and load translation strings from sources: | |||
151 | 1. `File > New` | 151 | 1. `File > New` |
152 | 2. Choose your language | 152 | 2. Choose your language |
153 | 3. Save your `PO` file in `<your_module>/languages/<language code>/LC_MESSAGES/my_theme.po`. | 153 | 3. Save your `PO` file in `<your_module>/languages/<language code>/LC_MESSAGES/my_theme.po`. |
154 | 4. Go to `Catalog > Properties...` | 154 | 4. Go to `Catalog > Properties...` |
155 | 5. Fill the `Translation Properties` tab | 155 | 5. Fill the `Translation Properties` tab |
156 | 6. Add your source path in the `Sources Paths` tab | 156 | 6. Add your source path in the `Sources Paths` tab |
157 | 7. In the `Sources Keywords` tab uncheck "Also use default keywords" and add the following lines: | 157 | 7. In the `Sources Keywords` tab uncheck "Also use default keywords" and add the following lines: |
158 | 158 | ||
159 | ``` | 159 | ``` |
160 | my_theme_t | 160 | my_theme_t |
161 | my_theme_t:1,2 | 161 | 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 @@ | |||
1 | msgid "" | ||
2 | msgstr "" | ||
3 | "Project-Id-Version: Shaarli\n" | ||
4 | "Report-Msgid-Bugs-To: \n" | ||
5 | "POT-Creation-Date: 2020-02-11 09:31+0900\n" | ||
6 | "PO-Revision-Date: 2020-02-11 10:54+0900\n" | ||
7 | "Last-Translator: yude <yudesleepy@gmail.com>\n" | ||
8 | "Language-Team: Shaarli\n" | ||
9 | "Language: ja\n" | ||
10 | "MIME-Version: 1.0\n" | ||
11 | "Content-Type: text/plain; charset=UTF-8\n" | ||
12 | "Content-Transfer-Encoding: 8bit\n" | ||
13 | "X-Generator: Poedit 2.3\n" | ||
14 | "X-Poedit-Basepath: ../../../..\n" | ||
15 | "Plural-Forms: nplurals=2; plural=(n != 1);\n" | ||
16 | "X-Poedit-SourceCharset: UTF-8\n" | ||
17 | "X-Poedit-KeywordsList: t:1,2;t\n" | ||
18 | "X-Poedit-SearchPath-0: .\n" | ||
19 | "X-Poedit-SearchPathExcluded-0: node_modules\n" | ||
20 | "X-Poedit-SearchPathExcluded-1: vendor\n" | ||
21 | |||
22 | #: application/ApplicationUtils.php:153 | ||
23 | #, php-format | ||
24 | msgid "" | ||
25 | "Your PHP version is obsolete! Shaarli requires at least PHP %s, and thus " | ||
26 | "cannot run. Your PHP version has known security vulnerabilities and should " | ||
27 | "be updated as soon as possible." | ||
28 | msgstr "" | ||
29 | "使用している PHP のバージョンが古すぎます! Shaarli の実行には最低でも PHP %s " | ||
30 | "が必要です。 現在使用している PHP のバージョンには脆弱性があり、できるだけ速" | ||
31 | "やかにアップデートするべきです。" | ||
32 | |||
33 | #: application/ApplicationUtils.php:183 application/ApplicationUtils.php:195 | ||
34 | msgid "directory is not readable" | ||
35 | msgstr "ディレクトリを読み込めません" | ||
36 | |||
37 | #: application/ApplicationUtils.php:198 | ||
38 | msgid "directory is not writable" | ||
39 | msgstr "ディレクトリに書き込めません" | ||
40 | |||
41 | #: application/ApplicationUtils.php:216 | ||
42 | msgid "file is not readable" | ||
43 | msgstr "ファイルを読み取る権限がありません" | ||
44 | |||
45 | #: application/ApplicationUtils.php:219 | ||
46 | msgid "file is not writable" | ||
47 | msgstr "ファイルを書き込む権限がありません" | ||
48 | |||
49 | #: application/Cache.php:16 | ||
50 | #, php-format | ||
51 | msgid "Cannot purge %s: no directory" | ||
52 | msgstr "%s を削除できません: ディレクトリが存在しません" | ||
53 | |||
54 | #: application/FeedBuilder.php:151 | ||
55 | msgid "Direct link" | ||
56 | msgstr "ダイレクトリンク" | ||
57 | |||
58 | #: application/FeedBuilder.php:153 | ||
59 | #: tmp/daily.b91ef64efc3688266305ea9b42e5017e.rtpl.php:88 | ||
60 | #: tmp/linklist.b91ef64efc3688266305ea9b42e5017e.rtpl.php:178 | ||
61 | msgid "Permalink" | ||
62 | msgstr "パーマリンク" | ||
63 | |||
64 | #: application/History.php:174 | ||
65 | msgid "History file isn't readable or writable" | ||
66 | msgstr "履歴ファイルを読み込む、または書き込むための権限がありません" | ||
67 | |||
68 | #: application/History.php:185 | ||
69 | msgid "Could not parse history file" | ||
70 | msgstr "履歴ファイルを正常に復元できませんでした" | ||
71 | |||
72 | #: application/Languages.php:177 | ||
73 | msgid "Automatic" | ||
74 | msgstr "自動" | ||
75 | |||
76 | #: application/Languages.php:178 | ||
77 | msgid "English" | ||
78 | msgstr "英語" | ||
79 | |||
80 | #: application/Languages.php:179 | ||
81 | msgid "French" | ||
82 | msgstr "フランス語" | ||
83 | |||
84 | #: application/Languages.php:180 | ||
85 | msgid "German" | ||
86 | msgstr "ドイツ語" | ||
87 | |||
88 | #: application/LinkDB.php:136 | ||
89 | msgid "You are not authorized to add a link." | ||
90 | msgstr "リンクを追加するには、ログインする必要があります。" | ||
91 | |||
92 | #: application/LinkDB.php:139 | ||
93 | msgid "Internal Error: A link should always have an id and URL." | ||
94 | msgstr "エラー: リンクにはIDとURLを登録しなければなりません。" | ||
95 | |||
96 | #: application/LinkDB.php:142 | ||
97 | msgid "You must specify an integer as a key." | ||
98 | msgstr "正常なキーの値ではありません。" | ||
99 | |||
100 | #: application/LinkDB.php:145 | ||
101 | msgid "Array offset and link ID must be equal." | ||
102 | msgstr "Array オフセットとリンクのIDは同じでなければなりません。" | ||
103 | |||
104 | #: application/LinkDB.php:251 | ||
105 | #: tmp/page.footer.b91ef64efc3688266305ea9b42e5017e.rtpl.php:14 | ||
106 | #: tmp/page.footer.b91ef64efc3688266305ea9b42e5017e.rtpl.php:48 | ||
107 | #: tmp/page.footer.cedf684561d925457130839629000a81.rtpl.php:14 | ||
108 | #: tmp/page.footer.cedf684561d925457130839629000a81.rtpl.php:48 | ||
109 | msgid "" | ||
110 | "The personal, minimalist, super-fast, database free, bookmarking service" | ||
111 | msgstr "" | ||
112 | "個人向けの、ミニマムで高速でかつデータベースのいらないブックマークサービス" | ||
113 | |||
114 | #: application/LinkDB.php:253 | ||
115 | msgid "" | ||
116 | "Welcome to Shaarli! This is your first public bookmark. To edit or delete " | ||
117 | "me, you must first login.\n" | ||
118 | "\n" | ||
119 | "To learn how to use Shaarli, consult the link \"Documentation\" at the " | ||
120 | "bottom of this page.\n" | ||
121 | "\n" | ||
122 | "You use the community supported version of the original Shaarli project, by " | ||
123 | "Sebastien Sauvage." | ||
124 | msgstr "" | ||
125 | "Shaarli へようこそ! これはあなたの最初の公開ブックマークです。これを編集した" | ||
126 | "り削除したりするには、ログインする必要があります。\n" | ||
127 | "\n" | ||
128 | "Shaarli の使い方を知るには、このページの下にある「ドキュメント」のリンクを開" | ||
129 | "いてください。\n" | ||
130 | "\n" | ||
131 | "あなたは Sebastien Sauvage による、コミュニティーサポートのあるバージョンのオ" | ||
132 | "リジナルのShaarli プロジェクトを使用しています。" | ||
133 | |||
134 | #: application/LinkDB.php:267 | ||
135 | msgid "My secret stuff... - Pastebin.com" | ||
136 | msgstr "わたしのひ💗み💗つ💗 - Pastebin.com" | ||
137 | |||
138 | #: application/LinkDB.php:269 | ||
139 | msgid "Shhhh! I'm a private link only YOU can see. You can delete me too." | ||
140 | msgstr "" | ||
141 | "シーッ! これはあなたしか見られないプライベートリンクです。消すこともできま" | ||
142 | "す。" | ||
143 | |||
144 | #: application/LinkFilter.php:452 | ||
145 | msgid "The link you are trying to reach does not exist or has been deleted." | ||
146 | msgstr "開こうとしたリンクは存在しないか、削除されています。" | ||
147 | |||
148 | #: application/NetscapeBookmarkUtils.php:35 | ||
149 | msgid "Invalid export selection:" | ||
150 | msgstr "不正なエクスポートの選択:" | ||
151 | |||
152 | #: application/NetscapeBookmarkUtils.php:81 | ||
153 | #, php-format | ||
154 | msgid "File %s (%d bytes) " | ||
155 | msgstr "ファイル %s (%d バイト) " | ||
156 | |||
157 | #: application/NetscapeBookmarkUtils.php:83 | ||
158 | msgid "has an unknown file format. Nothing was imported." | ||
159 | msgstr "は不明なファイル形式です。インポートは中止されました。" | ||
160 | |||
161 | #: application/NetscapeBookmarkUtils.php:86 | ||
162 | #, php-format | ||
163 | msgid "" | ||
164 | "was successfully processed in %d seconds: %d links imported, %d links " | ||
165 | "overwritten, %d links skipped." | ||
166 | msgstr "" | ||
167 | "が %d 秒で処理され、%d 件のリンクがインポートされ、%d 件のリンクが上書きさ" | ||
168 | "れ、%d 件のリンクがスキップされました。" | ||
169 | |||
170 | #: application/PageBuilder.php:168 | ||
171 | msgid "The page you are trying to reach does not exist or has been deleted." | ||
172 | msgstr "あなたが開こうとしたページは存在しないか、削除されています。" | ||
173 | |||
174 | #: application/PageBuilder.php:170 | ||
175 | msgid "404 Not Found" | ||
176 | msgstr "404 ページが存在しません" | ||
177 | |||
178 | #: application/PluginManager.php:243 | ||
179 | #, php-format | ||
180 | msgid "Plugin \"%s\" files not found." | ||
181 | msgstr "プラグイン「%s」のファイルが存在しません。" | ||
182 | |||
183 | #: application/Updater.php:76 | ||
184 | msgid "Couldn't retrieve Updater class methods." | ||
185 | msgstr "アップデーターのクラスメゾットを受信できませんでした。" | ||
186 | |||
187 | #: application/Updater.php:532 | ||
188 | msgid "An error occurred while running the update " | ||
189 | msgstr "更新中に問題が発生しました " | ||
190 | |||
191 | #: application/Updater.php:572 | ||
192 | msgid "Updates file path is not set, can't write updates." | ||
193 | msgstr "更新するファイルのパスが指定されていないため、更新を書き込めません。" | ||
194 | |||
195 | #: application/Updater.php:577 | ||
196 | msgid "Unable to write updates in " | ||
197 | msgstr "更新を次の項目に書き込めませんでした: " | ||
198 | |||
199 | #: application/Utils.php:376 tests/UtilsTest.php:340 | ||
200 | msgid "Setting not set" | ||
201 | msgstr "未設定" | ||
202 | |||
203 | #: application/Utils.php:383 tests/UtilsTest.php:338 tests/UtilsTest.php:339 | ||
204 | msgid "Unlimited" | ||
205 | msgstr "無制限" | ||
206 | |||
207 | #: application/Utils.php:386 tests/UtilsTest.php:335 tests/UtilsTest.php:336 | ||
208 | #: tests/UtilsTest.php:350 | ||
209 | msgid "B" | ||
210 | msgstr "B" | ||
211 | |||
212 | #: application/Utils.php:386 tests/UtilsTest.php:329 tests/UtilsTest.php:330 | ||
213 | #: tests/UtilsTest.php:337 | ||
214 | msgid "kiB" | ||
215 | msgstr "kiB" | ||
216 | |||
217 | #: application/Utils.php:386 tests/UtilsTest.php:331 tests/UtilsTest.php:332 | ||
218 | #: tests/UtilsTest.php:348 tests/UtilsTest.php:349 | ||
219 | msgid "MiB" | ||
220 | msgstr "MiB" | ||
221 | |||
222 | #: application/Utils.php:386 tests/UtilsTest.php:333 tests/UtilsTest.php:334 | ||
223 | msgid "GiB" | ||
224 | msgstr "GiB" | ||
225 | |||
226 | #: application/config/ConfigJson.php:52 application/config/ConfigPhp.php:121 | ||
227 | msgid "" | ||
228 | "Shaarli could not create the config file. Please make sure Shaarli has the " | ||
229 | "right to write in the folder is it installed in." | ||
230 | msgstr "" | ||
231 | "Shaarli は設定ファイルを作成できませんでした。Shaarli が正しい権限下に置かれ" | ||
232 | "ていて、インストールされているディレクトリに書き込みできることを確認してくだ" | ||
233 | "さい。" | ||
234 | |||
235 | #: application/config/ConfigManager.php:135 | ||
236 | msgid "Invalid setting key parameter. String expected, got: " | ||
237 | msgstr "" | ||
238 | "不正なキーの値です。文字列が想定されていますが、次のように入力されました: " | ||
239 | |||
240 | #: application/config/exception/MissingFieldConfigException.php:21 | ||
241 | #, php-format | ||
242 | msgid "Configuration value is required for %s" | ||
243 | msgstr "%s には設定が必要です" | ||
244 | |||
245 | #: application/config/exception/PluginConfigOrderException.php:15 | ||
246 | msgid "An error occurred while trying to save plugins loading order." | ||
247 | msgstr "プラグインの読込順を変更する際にエラーが発生しました。" | ||
248 | |||
249 | #: application/config/exception/UnauthorizedConfigException.php:16 | ||
250 | msgid "You are not authorized to alter config." | ||
251 | msgstr "設定を変更する権限がありません。" | ||
252 | |||
253 | #: application/exceptions/IOException.php:19 | ||
254 | msgid "Error accessing" | ||
255 | msgstr "読込中にエラーが発生しました" | ||
256 | |||
257 | #: index.php:142 | ||
258 | msgid "Shared links on " | ||
259 | msgstr "次において共有されたリンク:" | ||
260 | |||
261 | #: index.php:164 | ||
262 | msgid "Insufficient permissions:" | ||
263 | msgstr "権限がありません:" | ||
264 | |||
265 | #: index.php:303 | ||
266 | msgid "I said: NO. You are banned for the moment. Go away." | ||
267 | msgstr "あなたはこのサーバーからBANされています。" | ||
268 | |||
269 | #: index.php:368 | ||
270 | msgid "Wrong login/password." | ||
271 | msgstr "不正なユーザー名、またはパスワードです。" | ||
272 | |||
273 | #: index.php:576 tmp/page.header.b91ef64efc3688266305ea9b42e5017e.rtpl.php:42 | ||
274 | #: tmp/page.header.cedf684561d925457130839629000a81.rtpl.php:42 | ||
275 | msgid "Daily" | ||
276 | msgstr "デイリー" | ||
277 | |||
278 | #: index.php:681 tmp/loginform.b91ef64efc3688266305ea9b42e5017e.rtpl.php:28 | ||
279 | #: tmp/loginform.b91ef64efc3688266305ea9b42e5017e.rtpl.php:44 | ||
280 | #: tmp/page.header.b91ef64efc3688266305ea9b42e5017e.rtpl.php:71 | ||
281 | #: tmp/page.header.b91ef64efc3688266305ea9b42e5017e.rtpl.php:95 | ||
282 | #: tmp/page.header.cedf684561d925457130839629000a81.rtpl.php:71 | ||
283 | #: tmp/page.header.cedf684561d925457130839629000a81.rtpl.php:95 | ||
284 | msgid "Login" | ||
285 | msgstr "ログイン" | ||
286 | |||
287 | #: index.php:722 tmp/page.header.b91ef64efc3688266305ea9b42e5017e.rtpl.php:39 | ||
288 | #: tmp/page.header.cedf684561d925457130839629000a81.rtpl.php:39 | ||
289 | msgid "Picture wall" | ||
290 | msgstr "ピクチャウォール" | ||
291 | |||
292 | #: index.php:770 tmp/page.header.b91ef64efc3688266305ea9b42e5017e.rtpl.php:36 | ||
293 | #: tmp/page.header.cedf684561d925457130839629000a81.rtpl.php:36 | ||
294 | #: tmp/tag.cloud.b91ef64efc3688266305ea9b42e5017e.rtpl.php:19 | ||
295 | msgid "Tag cloud" | ||
296 | msgstr "タグクラウド" | ||
297 | |||
298 | #: index.php:803 tmp/tag.list.b91ef64efc3688266305ea9b42e5017e.rtpl.php:19 | ||
299 | msgid "Tag list" | ||
300 | msgstr "タグ一覧" | ||
301 | |||
302 | #: index.php:1028 tmp/page.header.b91ef64efc3688266305ea9b42e5017e.rtpl.php:31 | ||
303 | #: tmp/page.header.cedf684561d925457130839629000a81.rtpl.php:31 | ||
304 | msgid "Tools" | ||
305 | msgstr "ツール" | ||
306 | |||
307 | #: index.php:1037 | ||
308 | msgid "You are not supposed to change a password on an Open Shaarli." | ||
309 | msgstr "" | ||
310 | "公開されている Shaarli において、パスワードを変更することは想定されていませ" | ||
311 | "ん。" | ||
312 | |||
313 | #: index.php:1042 index.php:1084 index.php:1160 index.php:1191 index.php:1291 | ||
314 | msgid "Wrong token." | ||
315 | msgstr "不正なトークンです。" | ||
316 | |||
317 | #: index.php:1047 | ||
318 | msgid "The old password is not correct." | ||
319 | msgstr "元のパスワードが正しくありません。" | ||
320 | |||
321 | #: index.php:1067 | ||
322 | msgid "Your password has been changed" | ||
323 | msgstr "あなたのパスワードは変更されました" | ||
324 | |||
325 | #: index.php:1072 | ||
326 | #: tmp/changepassword.b91ef64efc3688266305ea9b42e5017e.rtpl.php:13 | ||
327 | #: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:29 | ||
328 | msgid "Change password" | ||
329 | msgstr "パスワードを変更" | ||
330 | |||
331 | #: index.php:1120 | ||
332 | msgid "Configuration was saved." | ||
333 | msgstr "設定は保存されました。" | ||
334 | |||
335 | #: index.php:1143 tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:24 | ||
336 | msgid "Configure" | ||
337 | msgstr "設定" | ||
338 | |||
339 | #: index.php:1154 tmp/changetag.b91ef64efc3688266305ea9b42e5017e.rtpl.php:13 | ||
340 | #: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:36 | ||
341 | msgid "Manage tags" | ||
342 | msgstr "タグを設定" | ||
343 | |||
344 | #: index.php:1172 | ||
345 | #, php-format | ||
346 | msgid "The tag was removed from %d link." | ||
347 | msgid_plural "The tag was removed from %d links." | ||
348 | msgstr[0] "%d 件のリンクからタグが削除されました。" | ||
349 | msgstr[1] "The tag was removed from %d links." | ||
350 | |||
351 | #: index.php:1173 | ||
352 | #, php-format | ||
353 | msgid "The tag was renamed in %d link." | ||
354 | msgid_plural "The tag was renamed in %d links." | ||
355 | msgstr[0] "タグが %d 件のリンクにおいて、名前が変更されました。" | ||
356 | msgstr[1] "タグが %d 件のリンクにおいて、名前が変更されました。" | ||
357 | |||
358 | #: index.php:1181 tmp/addlink.b91ef64efc3688266305ea9b42e5017e.rtpl.php:13 | ||
359 | msgid "Shaare a new link" | ||
360 | msgstr "新しいリンクを追加" | ||
361 | |||
362 | #: index.php:1351 tmp/editlink.b91ef64efc3688266305ea9b42e5017e.rtpl.php:14 | ||
363 | #: tmp/linklist.b91ef64efc3688266305ea9b42e5017e.rtpl.php:170 | ||
364 | msgid "Edit" | ||
365 | msgstr "共有" | ||
366 | |||
367 | #: index.php:1351 index.php:1421 | ||
368 | #: tmp/editlink.b91ef64efc3688266305ea9b42e5017e.rtpl.php:16 | ||
369 | #: tmp/page.header.b91ef64efc3688266305ea9b42e5017e.rtpl.php:26 | ||
370 | #: tmp/page.header.cedf684561d925457130839629000a81.rtpl.php:26 | ||
371 | msgid "Shaare" | ||
372 | msgstr "Shaare" | ||
373 | |||
374 | #: index.php:1390 | ||
375 | msgid "Note: " | ||
376 | msgstr "注: " | ||
377 | |||
378 | #: index.php:1430 tmp/export.b91ef64efc3688266305ea9b42e5017e.rtpl.php:65 | ||
379 | msgid "Export" | ||
380 | msgstr "エクスポート" | ||
381 | |||
382 | #: index.php:1492 tmp/import.b91ef64efc3688266305ea9b42e5017e.rtpl.php:83 | ||
383 | msgid "Import" | ||
384 | msgstr "インポート" | ||
385 | |||
386 | #: index.php:1502 | ||
387 | #, php-format | ||
388 | msgid "" | ||
389 | "The file you are trying to upload is probably bigger than what this " | ||
390 | "webserver can accept (%s). Please upload in smaller chunks." | ||
391 | msgstr "" | ||
392 | "あなたがアップロードしようとしているファイルは、サーバーが許可しているファイ" | ||
393 | "ルサイズ (%s) よりも大きいです。もう少し小さいものをアップロードしてくださ" | ||
394 | "い。" | ||
395 | |||
396 | #: index.php:1541 tmp/pluginsadmin.b91ef64efc3688266305ea9b42e5017e.rtpl.php:26 | ||
397 | #: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:22 | ||
398 | msgid "Plugin administration" | ||
399 | msgstr "プラグイン管理" | ||
400 | |||
401 | #: index.php:1706 | ||
402 | msgid "Search: " | ||
403 | msgstr "検索: " | ||
404 | |||
405 | #: index.php:1933 | ||
406 | #, php-format | ||
407 | msgid "" | ||
408 | "<pre>Sessions do not seem to work correctly on your server.<br>Make sure the " | ||
409 | "variable \"session.save_path\" is set correctly in your PHP config, and that " | ||
410 | "you have write access to it.<br>It currently points to %s.<br>On some " | ||
411 | "browsers, accessing your server via a hostname like 'localhost' or any " | ||
412 | "custom hostname without a dot causes cookie storage to fail. We recommend " | ||
413 | "accessing your server via it's IP address or Fully Qualified Domain Name.<br>" | ||
414 | msgstr "" | ||
415 | "<pre>セッションが正常にあなたのサーバー上で稼働していないようです。<br>PHP の" | ||
416 | "設定ファイル内にて、正しく \"session.save_path\" の値が設定されていることと、" | ||
417 | "権限が間違っていないことを確認してください。<br>現在 %s からPHPの設定ファイル" | ||
418 | "を読み込んでいます。<br>一部のブラウザーにおいて、localhost や他のドットを含" | ||
419 | "まないホスト名にてサーバーにアクセスする際に、クッキーを保存できないことがあ" | ||
420 | "ります。IP アドレスや完全なドメイン名でサーバーにアクセスすることをおすすめし" | ||
421 | "ます。<br>" | ||
422 | |||
423 | #: index.php:1943 | ||
424 | msgid "Click to try again." | ||
425 | msgstr "クリックして再度試します。" | ||
426 | |||
427 | #: plugins/addlink_toolbar/addlink_toolbar.php:29 | ||
428 | msgid "URI" | ||
429 | msgstr "URI" | ||
430 | |||
431 | #: plugins/addlink_toolbar/addlink_toolbar.php:33 | ||
432 | #: tmp/addlink.b91ef64efc3688266305ea9b42e5017e.rtpl.php:19 | ||
433 | msgid "Add link" | ||
434 | msgstr "リンクを追加" | ||
435 | |||
436 | #: plugins/addlink_toolbar/addlink_toolbar.php:50 | ||
437 | msgid "Adds the addlink input on the linklist page." | ||
438 | msgstr "リンク一覧のページに、リンクを追加するためのフォームを表示する。" | ||
439 | |||
440 | #: plugins/archiveorg/archiveorg.php:23 | ||
441 | msgid "View on archive.org" | ||
442 | msgstr "archive.org 上で表示する" | ||
443 | |||
444 | #: plugins/archiveorg/archiveorg.php:36 | ||
445 | msgid "For each link, add an Archive.org icon." | ||
446 | msgstr "それぞれのリンクに、Archive.org のアイコンを追加する。" | ||
447 | |||
448 | #: plugins/demo_plugin/demo_plugin.php:465 | ||
449 | msgid "" | ||
450 | "A demo plugin covering all use cases for template designers and plugin " | ||
451 | "developers." | ||
452 | msgstr "" | ||
453 | "テンプレートのデザイナーや、プラグインの開発者のためのすべての状況に対応でき" | ||
454 | "るデモプラグインです。" | ||
455 | |||
456 | #: plugins/isso/isso.php:20 | ||
457 | msgid "" | ||
458 | "Isso plugin error: Please define the \"ISSO_SERVER\" setting in the plugin " | ||
459 | "administration page." | ||
460 | msgstr "" | ||
461 | "Isso プラグインエラー: \"ISSO_SERVER\" の値をプラグイン管理ページにて指定して" | ||
462 | "ください。" | ||
463 | |||
464 | #: plugins/isso/isso.php:63 | ||
465 | msgid "Let visitor comment your shaares on permalinks with Isso." | ||
466 | msgstr "" | ||
467 | "Isso を使って、あなたのパーマリンク上のリンクに第三者がコメントを残すことがで" | ||
468 | "きます。" | ||
469 | |||
470 | #: plugins/isso/isso.php:64 | ||
471 | msgid "Isso server URL (without 'http://')" | ||
472 | msgstr "Isso server URL ('http://' 抜き)" | ||
473 | |||
474 | #: plugins/markdown/markdown.php:158 | ||
475 | msgid "Description will be rendered with" | ||
476 | msgstr "説明は次の方法で描画されます:" | ||
477 | |||
478 | #: plugins/markdown/markdown.php:159 | ||
479 | msgid "Markdown syntax documentation" | ||
480 | msgstr "マークダウン形式のドキュメント" | ||
481 | |||
482 | #: plugins/markdown/markdown.php:160 | ||
483 | msgid "Markdown syntax" | ||
484 | msgstr "マークダウン形式" | ||
485 | |||
486 | #: plugins/markdown/markdown.php:339 | ||
487 | msgid "" | ||
488 | "Render shaare description with Markdown syntax.<br><strong>Warning</" | ||
489 | "strong>:\n" | ||
490 | "If your shaared descriptions contained HTML tags before enabling the " | ||
491 | "markdown plugin,\n" | ||
492 | "enabling it might break your page.\n" | ||
493 | "See the <a href=\"https://github.com/shaarli/Shaarli/tree/master/plugins/" | ||
494 | "markdown#html-rendering\">README</a>." | ||
495 | msgstr "" | ||
496 | "リンクの説明をマークダウン形式で表示します。<br><strong>警告</strong>:\n" | ||
497 | "リンクの説明にHTMLタグがこのプラグインを有効にする前に含まれていた場合、\n" | ||
498 | "正常にページを表示できなくなるかもしれません。\n" | ||
499 | "詳しくは <a href=\"https://github.com/shaarli/Shaarli/tree/master/plugins/" | ||
500 | "markdown#html-rendering\">README</a> をご覧ください。" | ||
501 | |||
502 | #: plugins/piwik/piwik.php:21 | ||
503 | msgid "" | ||
504 | "Piwik plugin error: Please define PIWIK_URL and PIWIK_SITEID in the plugin " | ||
505 | "administration page." | ||
506 | msgstr "" | ||
507 | "Piwik プラグインエラー: PIWIK_URL と PIWIK_SITEID の値をプラグイン管理ページ" | ||
508 | "で指定してください。" | ||
509 | |||
510 | #: plugins/piwik/piwik.php:70 | ||
511 | msgid "A plugin that adds Piwik tracking code to Shaarli pages." | ||
512 | msgstr "Piwik のトラッキングコードをShaarliに追加するプラグインです。" | ||
513 | |||
514 | #: plugins/piwik/piwik.php:71 | ||
515 | msgid "Piwik URL" | ||
516 | msgstr "Piwik URL" | ||
517 | |||
518 | #: plugins/piwik/piwik.php:72 | ||
519 | msgid "Piwik site ID" | ||
520 | msgstr "Piwik サイトID" | ||
521 | |||
522 | #: plugins/playvideos/playvideos.php:22 | ||
523 | msgid "Video player" | ||
524 | msgstr "動画プレイヤー" | ||
525 | |||
526 | #: plugins/playvideos/playvideos.php:25 | ||
527 | msgid "Play Videos" | ||
528 | msgstr "動画を再生" | ||
529 | |||
530 | #: plugins/playvideos/playvideos.php:56 | ||
531 | msgid "Add a button in the toolbar allowing to watch all videos." | ||
532 | msgstr "すべての動画を閲覧するボタンをツールバーに追加します。" | ||
533 | |||
534 | #: plugins/playvideos/youtube_playlist.js:214 | ||
535 | msgid "plugins/playvideos/jquery-1.11.2.min.js" | ||
536 | msgstr "plugins/playvideos/jquery-1.11.2.min.js" | ||
537 | |||
538 | #: plugins/pubsubhubbub/pubsubhubbub.php:69 | ||
539 | #, php-format | ||
540 | msgid "Could not publish to PubSubHubbub: %s" | ||
541 | msgstr "PubSubHubbub に登録できませんでした: %s" | ||
542 | |||
543 | #: plugins/pubsubhubbub/pubsubhubbub.php:95 | ||
544 | #, php-format | ||
545 | msgid "Could not post to %s" | ||
546 | msgstr "%s に登録できませんでした" | ||
547 | |||
548 | #: plugins/pubsubhubbub/pubsubhubbub.php:99 | ||
549 | #, php-format | ||
550 | msgid "Bad response from the hub %s" | ||
551 | msgstr "ハブ %s からの不正なレスポンス" | ||
552 | |||
553 | #: plugins/pubsubhubbub/pubsubhubbub.php:110 | ||
554 | msgid "Enable PubSubHubbub feed publishing." | ||
555 | msgstr "PubSubHubbub へのフィードを公開する。" | ||
556 | |||
557 | #: plugins/qrcode/qrcode.php:69 plugins/wallabag/wallabag.php:68 | ||
558 | msgid "For each link, add a QRCode icon." | ||
559 | msgstr "それぞれのリンクについて、QRコードのアイコンを追加する。" | ||
560 | |||
561 | #: plugins/wallabag/wallabag.php:21 | ||
562 | msgid "" | ||
563 | "Wallabag plugin error: Please define the \"WALLABAG_URL\" setting in the " | ||
564 | "plugin administration page." | ||
565 | msgstr "" | ||
566 | "Wallabag プラグインエラー: \"WALLABAG_URL\" の値をプラグイン管理ページにおい" | ||
567 | "て指定してください。" | ||
568 | |||
569 | #: plugins/wallabag/wallabag.php:47 | ||
570 | msgid "Save to wallabag" | ||
571 | msgstr "Wallabag に保存" | ||
572 | |||
573 | #: plugins/wallabag/wallabag.php:69 | ||
574 | msgid "Wallabag API URL" | ||
575 | msgstr "Wallabag のAPIのURL" | ||
576 | |||
577 | #: plugins/wallabag/wallabag.php:70 | ||
578 | msgid "Wallabag API version (1 or 2)" | ||
579 | msgstr "Wallabag のAPIのバージョン (1 または 2)" | ||
580 | |||
581 | #: tests/LanguagesTest.php:214 tests/LanguagesTest.php:227 | ||
582 | #: tests/languages/fr/LanguagesFrTest.php:160 | ||
583 | #: tests/languages/fr/LanguagesFrTest.php:173 | ||
584 | #: tmp/page.header.b91ef64efc3688266305ea9b42e5017e.rtpl.php:81 | ||
585 | #: tmp/page.header.cedf684561d925457130839629000a81.rtpl.php:81 | ||
586 | msgid "Search" | ||
587 | msgid_plural "Search" | ||
588 | msgstr[0] "検索" | ||
589 | msgstr[1] "検索" | ||
590 | |||
591 | #: tmp/404.b91ef64efc3688266305ea9b42e5017e.rtpl.php:12 | ||
592 | msgid "Sorry, nothing to see here." | ||
593 | msgstr "すみませんが、ここには何もありません。" | ||
594 | |||
595 | #: tmp/addlink.b91ef64efc3688266305ea9b42e5017e.rtpl.php:16 | ||
596 | msgid "URL or leave empty to post a note" | ||
597 | msgstr "URL を入力するか、空欄にするとノートを投稿します" | ||
598 | |||
599 | #: tmp/changepassword.b91ef64efc3688266305ea9b42e5017e.rtpl.php:16 | ||
600 | msgid "Current password" | ||
601 | msgstr "現在のパスワード" | ||
602 | |||
603 | #: tmp/changepassword.b91ef64efc3688266305ea9b42e5017e.rtpl.php:19 | ||
604 | msgid "New password" | ||
605 | msgstr "新しいパスワード" | ||
606 | |||
607 | #: tmp/changepassword.b91ef64efc3688266305ea9b42e5017e.rtpl.php:23 | ||
608 | msgid "Change" | ||
609 | msgstr "変更" | ||
610 | |||
611 | #: tmp/changetag.b91ef64efc3688266305ea9b42e5017e.rtpl.php:16 | ||
612 | #: tmp/import.b91ef64efc3688266305ea9b42e5017e.rtpl.php:77 | ||
613 | msgid "Tag" | ||
614 | msgstr "タグ" | ||
615 | |||
616 | #: tmp/changetag.b91ef64efc3688266305ea9b42e5017e.rtpl.php:24 | ||
617 | msgid "New name" | ||
618 | msgstr "変更先の名前" | ||
619 | |||
620 | #: tmp/changetag.b91ef64efc3688266305ea9b42e5017e.rtpl.php:31 | ||
621 | msgid "Case sensitive" | ||
622 | msgstr "大文字と小文字を区別" | ||
623 | |||
624 | #: tmp/changetag.b91ef64efc3688266305ea9b42e5017e.rtpl.php:34 | ||
625 | msgid "Rename" | ||
626 | msgstr "名前を変更" | ||
627 | |||
628 | #: tmp/changetag.b91ef64efc3688266305ea9b42e5017e.rtpl.php:35 | ||
629 | #: tmp/editlink.b91ef64efc3688266305ea9b42e5017e.rtpl.php:79 | ||
630 | #: tmp/linklist.b91ef64efc3688266305ea9b42e5017e.rtpl.php:172 | ||
631 | msgid "Delete" | ||
632 | msgstr "削除" | ||
633 | |||
634 | #: tmp/changetag.b91ef64efc3688266305ea9b42e5017e.rtpl.php:39 | ||
635 | msgid "You can also edit tags in the" | ||
636 | msgstr "次に含まれるタグを編集することもできます:" | ||
637 | |||
638 | #: tmp/changetag.b91ef64efc3688266305ea9b42e5017e.rtpl.php:39 | ||
639 | msgid "tag list" | ||
640 | msgstr "タグ一覧" | ||
641 | |||
642 | #: tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:29 | ||
643 | msgid "title" | ||
644 | msgstr "タイトル" | ||
645 | |||
646 | #: tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:43 | ||
647 | msgid "Home link" | ||
648 | msgstr "ホームのリンク先" | ||
649 | |||
650 | #: tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:44 | ||
651 | msgid "Default value" | ||
652 | msgstr "既定の値" | ||
653 | |||
654 | #: tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:58 | ||
655 | msgid "Theme" | ||
656 | msgstr "テーマ" | ||
657 | |||
658 | #: tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:87 | ||
659 | #: tmp/install.b91ef64efc3688266305ea9b42e5017e.rtpl.php:78 | ||
660 | msgid "Language" | ||
661 | msgstr "言語" | ||
662 | |||
663 | #: tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:116 | ||
664 | #: tmp/install.b91ef64efc3688266305ea9b42e5017e.rtpl.php:102 | ||
665 | msgid "Timezone" | ||
666 | msgstr "タイムゾーン" | ||
667 | |||
668 | #: tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:117 | ||
669 | #: tmp/install.b91ef64efc3688266305ea9b42e5017e.rtpl.php:103 | ||
670 | msgid "Continent" | ||
671 | msgstr "大陸" | ||
672 | |||
673 | #: tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:117 | ||
674 | #: tmp/install.b91ef64efc3688266305ea9b42e5017e.rtpl.php:103 | ||
675 | msgid "City" | ||
676 | msgstr "町" | ||
677 | |||
678 | #: tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:164 | ||
679 | msgid "Disable session cookie hijacking protection" | ||
680 | msgstr "不正ログイン防止のためのセッションクッキーを無効化" | ||
681 | |||
682 | #: tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:166 | ||
683 | msgid "Check this if you get disconnected or if your IP address changes often" | ||
684 | msgstr "" | ||
685 | "あなたが切断されたり、IPアドレスが頻繁に変わる環境下であるならチェックを入れ" | ||
686 | "てください" | ||
687 | |||
688 | #: tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:183 | ||
689 | msgid "Private links by default" | ||
690 | msgstr "既定でプライベートリンク" | ||
691 | |||
692 | #: tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:184 | ||
693 | msgid "All new links are private by default" | ||
694 | msgstr "すべての新規リンクをプライベートで作成" | ||
695 | |||
696 | #: tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:199 | ||
697 | msgid "RSS direct links" | ||
698 | msgstr "RSS 直リンク" | ||
699 | |||
700 | #: tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:200 | ||
701 | msgid "Check this to use direct URL instead of permalink in feeds" | ||
702 | msgstr "フィードでパーマリンクの代わりに直リンクを使う" | ||
703 | |||
704 | #: tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:215 | ||
705 | msgid "Hide public links" | ||
706 | msgstr "公開リンクを隠す" | ||
707 | |||
708 | #: tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:216 | ||
709 | msgid "Do not show any links if the user is not logged in" | ||
710 | msgstr "ログインしていないユーザーには何のリンクも表示しない" | ||
711 | |||
712 | #: tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:231 | ||
713 | #: tmp/install.b91ef64efc3688266305ea9b42e5017e.rtpl.php:150 | ||
714 | msgid "Check updates" | ||
715 | msgstr "更新を確認" | ||
716 | |||
717 | #: tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:232 | ||
718 | #: tmp/install.b91ef64efc3688266305ea9b42e5017e.rtpl.php:152 | ||
719 | msgid "Notify me when a new release is ready" | ||
720 | msgstr "新しいバージョンがリリースされたときに通知" | ||
721 | |||
722 | #: tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:247 | ||
723 | #: tmp/install.b91ef64efc3688266305ea9b42e5017e.rtpl.php:169 | ||
724 | msgid "Enable REST API" | ||
725 | msgstr "REST API を有効化" | ||
726 | |||
727 | #: tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:248 | ||
728 | #: tmp/install.b91ef64efc3688266305ea9b42e5017e.rtpl.php:170 | ||
729 | msgid "Allow third party software to use Shaarli such as mobile application" | ||
730 | msgstr "" | ||
731 | "モバイルアプリといったサードパーティーのソフトウェアにShaarliを使用することを" | ||
732 | "許可" | ||
733 | |||
734 | #: tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:263 | ||
735 | msgid "API secret" | ||
736 | msgstr "API シークレット" | ||
737 | |||
738 | #: tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:274 | ||
739 | #: tmp/editlink.b91ef64efc3688266305ea9b42e5017e.rtpl.php:74 | ||
740 | #: tmp/pluginsadmin.b91ef64efc3688266305ea9b42e5017e.rtpl.php:139 | ||
741 | #: tmp/pluginsadmin.b91ef64efc3688266305ea9b42e5017e.rtpl.php:199 | ||
742 | msgid "Save" | ||
743 | msgstr "保存" | ||
744 | |||
745 | #: tmp/daily.b91ef64efc3688266305ea9b42e5017e.rtpl.php:15 | ||
746 | msgid "The Daily Shaarli" | ||
747 | msgstr "デイリーSharli" | ||
748 | |||
749 | #: tmp/daily.b91ef64efc3688266305ea9b42e5017e.rtpl.php:17 | ||
750 | msgid "1 RSS entry per day" | ||
751 | msgstr "各日1つずつのRSS項目" | ||
752 | |||
753 | #: tmp/daily.b91ef64efc3688266305ea9b42e5017e.rtpl.php:37 | ||
754 | msgid "Previous day" | ||
755 | msgstr "前日" | ||
756 | |||
757 | #: tmp/daily.b91ef64efc3688266305ea9b42e5017e.rtpl.php:44 | ||
758 | msgid "All links of one day in a single page." | ||
759 | msgstr "1日に作成されたすべてのリンクです。" | ||
760 | |||
761 | #: tmp/daily.b91ef64efc3688266305ea9b42e5017e.rtpl.php:51 | ||
762 | msgid "Next day" | ||
763 | msgstr "翌日" | ||
764 | |||
765 | #: tmp/editlink.b91ef64efc3688266305ea9b42e5017e.rtpl.php:25 | ||
766 | msgid "Created:" | ||
767 | msgstr "作成:" | ||
768 | |||
769 | #: tmp/editlink.b91ef64efc3688266305ea9b42e5017e.rtpl.php:28 | ||
770 | msgid "URL" | ||
771 | msgstr "URL" | ||
772 | |||
773 | #: tmp/editlink.b91ef64efc3688266305ea9b42e5017e.rtpl.php:34 | ||
774 | msgid "Title" | ||
775 | msgstr "タイトル" | ||
776 | |||
777 | #: tmp/editlink.b91ef64efc3688266305ea9b42e5017e.rtpl.php:40 | ||
778 | #: tmp/pluginsadmin.b91ef64efc3688266305ea9b42e5017e.rtpl.php:42 | ||
779 | #: tmp/pluginsadmin.b91ef64efc3688266305ea9b42e5017e.rtpl.php:75 | ||
780 | #: tmp/pluginsadmin.b91ef64efc3688266305ea9b42e5017e.rtpl.php:99 | ||
781 | #: tmp/pluginsadmin.b91ef64efc3688266305ea9b42e5017e.rtpl.php:124 | ||
782 | msgid "Description" | ||
783 | msgstr "説明" | ||
784 | |||
785 | #: tmp/editlink.b91ef64efc3688266305ea9b42e5017e.rtpl.php:46 | ||
786 | msgid "Tags" | ||
787 | msgstr "タグ" | ||
788 | |||
789 | #: tmp/editlink.b91ef64efc3688266305ea9b42e5017e.rtpl.php:59 | ||
790 | #: tmp/export.b91ef64efc3688266305ea9b42e5017e.rtpl.php:36 | ||
791 | #: tmp/linklist.b91ef64efc3688266305ea9b42e5017e.rtpl.php:168 | ||
792 | msgid "Private" | ||
793 | msgstr "プライベート" | ||
794 | |||
795 | #: tmp/editlink.b91ef64efc3688266305ea9b42e5017e.rtpl.php:74 | ||
796 | msgid "Apply Changes" | ||
797 | msgstr "変更を適用" | ||
798 | |||
799 | #: tmp/export.b91ef64efc3688266305ea9b42e5017e.rtpl.php:16 | ||
800 | msgid "Export Database" | ||
801 | msgstr "データベースをエクスポート" | ||
802 | |||
803 | #: tmp/export.b91ef64efc3688266305ea9b42e5017e.rtpl.php:24 | ||
804 | msgid "Selection" | ||
805 | msgstr "選択済み" | ||
806 | |||
807 | #: tmp/export.b91ef64efc3688266305ea9b42e5017e.rtpl.php:31 | ||
808 | msgid "All" | ||
809 | msgstr "すべて" | ||
810 | |||
811 | #: tmp/export.b91ef64efc3688266305ea9b42e5017e.rtpl.php:41 | ||
812 | msgid "Public" | ||
813 | msgstr "公開" | ||
814 | |||
815 | #: tmp/export.b91ef64efc3688266305ea9b42e5017e.rtpl.php:52 | ||
816 | msgid "Prepend note permalinks with this Shaarli instance's URL" | ||
817 | msgstr "この Shaarli のインスタンスのURL にノートへのパーマリンクを付け加える" | ||
818 | |||
819 | #: tmp/export.b91ef64efc3688266305ea9b42e5017e.rtpl.php:53 | ||
820 | msgid "Useful to import bookmarks in a web browser" | ||
821 | msgstr "ウェブブラウザーのリンクをインポートするのに有効です" | ||
822 | |||
823 | #: tmp/import.b91ef64efc3688266305ea9b42e5017e.rtpl.php:16 | ||
824 | msgid "Import Database" | ||
825 | msgstr "データベースをインポート" | ||
826 | |||
827 | #: tmp/import.b91ef64efc3688266305ea9b42e5017e.rtpl.php:23 | ||
828 | msgid "Maximum size allowed:" | ||
829 | msgstr "最大サイズ:" | ||
830 | |||
831 | #: tmp/import.b91ef64efc3688266305ea9b42e5017e.rtpl.php:29 | ||
832 | msgid "Visibility" | ||
833 | msgstr "可視性" | ||
834 | |||
835 | #: tmp/import.b91ef64efc3688266305ea9b42e5017e.rtpl.php:36 | ||
836 | msgid "Use values from the imported file, default to public" | ||
837 | msgstr "インポート元のファイルの値を使用 (既定は公開リンクとなります)" | ||
838 | |||
839 | #: tmp/import.b91ef64efc3688266305ea9b42e5017e.rtpl.php:41 | ||
840 | msgid "Import all bookmarks as private" | ||
841 | msgstr "すべてのブックマーク項目をプライベートリンクとしてインポート" | ||
842 | |||
843 | #: tmp/import.b91ef64efc3688266305ea9b42e5017e.rtpl.php:46 | ||
844 | msgid "Import all bookmarks as public" | ||
845 | msgstr "すべてのブックマーク項目を公開リンクとしてインポート" | ||
846 | |||
847 | #: tmp/import.b91ef64efc3688266305ea9b42e5017e.rtpl.php:57 | ||
848 | msgid "Overwrite existing bookmarks" | ||
849 | msgstr "既に存在しているブックマークを上書き" | ||
850 | |||
851 | #: tmp/import.b91ef64efc3688266305ea9b42e5017e.rtpl.php:58 | ||
852 | msgid "Duplicates based on URL" | ||
853 | msgstr "URL による重複" | ||
854 | |||
855 | #: tmp/import.b91ef64efc3688266305ea9b42e5017e.rtpl.php:72 | ||
856 | msgid "Add default tags" | ||
857 | msgstr "既定のタグを追加" | ||
858 | |||
859 | #: tmp/install.b91ef64efc3688266305ea9b42e5017e.rtpl.php:22 | ||
860 | msgid "Install Shaarli" | ||
861 | msgstr "Shaarli をインストール" | ||
862 | |||
863 | #: tmp/install.b91ef64efc3688266305ea9b42e5017e.rtpl.php:25 | ||
864 | msgid "It looks like it's the first time you run Shaarli. Please configure it." | ||
865 | msgstr "どうやら Shaarli を初めて起動しているようです。設定してください。" | ||
866 | |||
867 | #: tmp/install.b91ef64efc3688266305ea9b42e5017e.rtpl.php:33 | ||
868 | #: tmp/loginform.b91ef64efc3688266305ea9b42e5017e.rtpl.php:30 | ||
869 | #: tmp/page.header.b91ef64efc3688266305ea9b42e5017e.rtpl.php:147 | ||
870 | #: tmp/page.header.cedf684561d925457130839629000a81.rtpl.php:147 | ||
871 | msgid "Username" | ||
872 | msgstr "ユーザー名" | ||
873 | |||
874 | #: tmp/install.b91ef64efc3688266305ea9b42e5017e.rtpl.php:48 | ||
875 | #: tmp/loginform.b91ef64efc3688266305ea9b42e5017e.rtpl.php:34 | ||
876 | #: tmp/page.header.b91ef64efc3688266305ea9b42e5017e.rtpl.php:148 | ||
877 | #: tmp/page.header.cedf684561d925457130839629000a81.rtpl.php:148 | ||
878 | msgid "Password" | ||
879 | msgstr "パスワード" | ||
880 | |||
881 | #: tmp/install.b91ef64efc3688266305ea9b42e5017e.rtpl.php:63 | ||
882 | msgid "Shaarli title" | ||
883 | msgstr "Shaarli のタイトル" | ||
884 | |||
885 | #: tmp/install.b91ef64efc3688266305ea9b42e5017e.rtpl.php:69 | ||
886 | msgid "My links" | ||
887 | msgstr "自分のリンク" | ||
888 | |||
889 | #: tmp/install.b91ef64efc3688266305ea9b42e5017e.rtpl.php:182 | ||
890 | msgid "Install" | ||
891 | msgstr "インストール" | ||
892 | |||
893 | #: tmp/linklist.b91ef64efc3688266305ea9b42e5017e.rtpl.php:14 | ||
894 | #: tmp/linklist.b91ef64efc3688266305ea9b42e5017e.rtpl.php:80 | ||
895 | msgid "shaare" | ||
896 | msgid_plural "shaares" | ||
897 | msgstr[0] "共有" | ||
898 | msgstr[1] "共有" | ||
899 | |||
900 | #: tmp/linklist.b91ef64efc3688266305ea9b42e5017e.rtpl.php:18 | ||
901 | #: tmp/linklist.b91ef64efc3688266305ea9b42e5017e.rtpl.php:84 | ||
902 | msgid "private link" | ||
903 | msgid_plural "private links" | ||
904 | msgstr[0] "プライベートリンク" | ||
905 | msgstr[1] "プライベートリンク" | ||
906 | |||
907 | #: tmp/linklist.b91ef64efc3688266305ea9b42e5017e.rtpl.php:31 | ||
908 | #: tmp/page.header.b91ef64efc3688266305ea9b42e5017e.rtpl.php:117 | ||
909 | #: tmp/page.header.cedf684561d925457130839629000a81.rtpl.php:117 | ||
910 | msgid "Search text" | ||
911 | msgstr "文字列で検索" | ||
912 | |||
913 | #: tmp/linklist.b91ef64efc3688266305ea9b42e5017e.rtpl.php:38 | ||
914 | #: tmp/page.header.b91ef64efc3688266305ea9b42e5017e.rtpl.php:124 | ||
915 | #: tmp/page.header.cedf684561d925457130839629000a81.rtpl.php:124 | ||
916 | #: tmp/tag.cloud.b91ef64efc3688266305ea9b42e5017e.rtpl.php:36 | ||
917 | #: tmp/tag.cloud.b91ef64efc3688266305ea9b42e5017e.rtpl.php:64 | ||
918 | #: tmp/tag.list.b91ef64efc3688266305ea9b42e5017e.rtpl.php:36 | ||
919 | #: tmp/tag.list.b91ef64efc3688266305ea9b42e5017e.rtpl.php:74 | ||
920 | msgid "Filter by tag" | ||
921 | msgstr "タグによって分類" | ||
922 | |||
923 | #: tmp/linklist.b91ef64efc3688266305ea9b42e5017e.rtpl.php:111 | ||
924 | msgid "Nothing found." | ||
925 | msgstr "何も見つかりませんでした。" | ||
926 | |||
927 | #: tmp/linklist.b91ef64efc3688266305ea9b42e5017e.rtpl.php:119 | ||
928 | #, php-format | ||
929 | msgid "%s result" | ||
930 | msgid_plural "%s results" | ||
931 | msgstr[0] "%s 件の結果" | ||
932 | msgstr[1] "%s 件の結果" | ||
933 | |||
934 | #: tmp/linklist.b91ef64efc3688266305ea9b42e5017e.rtpl.php:123 | ||
935 | msgid "for" | ||
936 | msgstr "for" | ||
937 | |||
938 | #: tmp/linklist.b91ef64efc3688266305ea9b42e5017e.rtpl.php:130 | ||
939 | msgid "tagged" | ||
940 | msgstr "タグ付けされた" | ||
941 | |||
942 | #: tmp/linklist.b91ef64efc3688266305ea9b42e5017e.rtpl.php:134 | ||
943 | msgid "Remove tag" | ||
944 | msgstr "タグを削除" | ||
945 | |||
946 | #: tmp/linklist.b91ef64efc3688266305ea9b42e5017e.rtpl.php:143 | ||
947 | msgid "with status" | ||
948 | msgstr "with status" | ||
949 | |||
950 | #: tmp/linklist.b91ef64efc3688266305ea9b42e5017e.rtpl.php:154 | ||
951 | msgid "without any tag" | ||
952 | msgstr "タグなし" | ||
953 | |||
954 | #: tmp/linklist.b91ef64efc3688266305ea9b42e5017e.rtpl.php:174 | ||
955 | #: tmp/page.footer.b91ef64efc3688266305ea9b42e5017e.rtpl.php:42 | ||
956 | #: tmp/page.footer.cedf684561d925457130839629000a81.rtpl.php:42 | ||
957 | msgid "Fold" | ||
958 | msgstr "畳む" | ||
959 | |||
960 | #: tmp/linklist.b91ef64efc3688266305ea9b42e5017e.rtpl.php:176 | ||
961 | msgid "Edited: " | ||
962 | msgstr "編集済み: " | ||
963 | |||
964 | #: tmp/linklist.b91ef64efc3688266305ea9b42e5017e.rtpl.php:180 | ||
965 | msgid "permalink" | ||
966 | msgstr "パーマリンク" | ||
967 | |||
968 | #: tmp/linklist.b91ef64efc3688266305ea9b42e5017e.rtpl.php:182 | ||
969 | msgid "Add tag" | ||
970 | msgstr "タグを追加" | ||
971 | |||
972 | #: tmp/linklist.paging.b91ef64efc3688266305ea9b42e5017e.rtpl.php:7 | ||
973 | #: tmp/linklist.paging.cedf684561d925457130839629000a81.rtpl.php:7 | ||
974 | msgid "Filters" | ||
975 | msgstr "分類" | ||
976 | |||
977 | #: tmp/linklist.paging.b91ef64efc3688266305ea9b42e5017e.rtpl.php:12 | ||
978 | #: tmp/linklist.paging.cedf684561d925457130839629000a81.rtpl.php:12 | ||
979 | msgid "Only display private links" | ||
980 | msgstr "プライベートリンクのみを表示" | ||
981 | |||
982 | #: tmp/linklist.paging.b91ef64efc3688266305ea9b42e5017e.rtpl.php:15 | ||
983 | #: tmp/linklist.paging.cedf684561d925457130839629000a81.rtpl.php:15 | ||
984 | msgid "Only display public links" | ||
985 | msgstr "公開リンクのみを表示" | ||
986 | |||
987 | #: tmp/linklist.paging.b91ef64efc3688266305ea9b42e5017e.rtpl.php:20 | ||
988 | #: tmp/linklist.paging.cedf684561d925457130839629000a81.rtpl.php:20 | ||
989 | msgid "Filter untagged links" | ||
990 | msgstr "タグ付けされていないリンクで分類" | ||
991 | |||
992 | #: tmp/linklist.paging.b91ef64efc3688266305ea9b42e5017e.rtpl.php:24 | ||
993 | #: tmp/linklist.paging.b91ef64efc3688266305ea9b42e5017e.rtpl.php:76 | ||
994 | #: tmp/linklist.paging.cedf684561d925457130839629000a81.rtpl.php:24 | ||
995 | #: tmp/linklist.paging.cedf684561d925457130839629000a81.rtpl.php:76 | ||
996 | #: tmp/page.footer.b91ef64efc3688266305ea9b42e5017e.rtpl.php:43 | ||
997 | #: tmp/page.footer.cedf684561d925457130839629000a81.rtpl.php:43 | ||
998 | msgid "Fold all" | ||
999 | msgstr "すべて畳む" | ||
1000 | |||
1001 | #: tmp/linklist.paging.b91ef64efc3688266305ea9b42e5017e.rtpl.php:69 | ||
1002 | #: tmp/linklist.paging.cedf684561d925457130839629000a81.rtpl.php:69 | ||
1003 | msgid "Links per page" | ||
1004 | msgstr "各ページをリンク" | ||
1005 | |||
1006 | #: tmp/loginform.b91ef64efc3688266305ea9b42e5017e.rtpl.php:15 | ||
1007 | msgid "" | ||
1008 | "You have been banned after too many failed login attempts. Try again later." | ||
1009 | msgstr "複数回に渡るログインへの失敗を検出しました。後でまた試してください。" | ||
1010 | |||
1011 | #: tmp/loginform.b91ef64efc3688266305ea9b42e5017e.rtpl.php:41 | ||
1012 | #: tmp/page.header.b91ef64efc3688266305ea9b42e5017e.rtpl.php:151 | ||
1013 | #: tmp/page.header.cedf684561d925457130839629000a81.rtpl.php:151 | ||
1014 | msgid "Remember me" | ||
1015 | msgstr "パスワードを保存" | ||
1016 | |||
1017 | #: tmp/page.footer.b91ef64efc3688266305ea9b42e5017e.rtpl.php:14 | ||
1018 | #: tmp/page.footer.b91ef64efc3688266305ea9b42e5017e.rtpl.php:48 | ||
1019 | #: tmp/page.footer.cedf684561d925457130839629000a81.rtpl.php:14 | ||
1020 | #: tmp/page.footer.cedf684561d925457130839629000a81.rtpl.php:48 | ||
1021 | msgid "by the Shaarli community" | ||
1022 | msgstr "by Shaarli コミュニティ" | ||
1023 | |||
1024 | #: tmp/page.footer.b91ef64efc3688266305ea9b42e5017e.rtpl.php:15 | ||
1025 | #: tmp/page.footer.cedf684561d925457130839629000a81.rtpl.php:15 | ||
1026 | msgid "Documentation" | ||
1027 | msgstr "ドキュメント" | ||
1028 | |||
1029 | #: tmp/page.footer.b91ef64efc3688266305ea9b42e5017e.rtpl.php:44 | ||
1030 | #: tmp/page.footer.cedf684561d925457130839629000a81.rtpl.php:44 | ||
1031 | msgid "Expand" | ||
1032 | msgstr "展開する" | ||
1033 | |||
1034 | #: tmp/page.footer.b91ef64efc3688266305ea9b42e5017e.rtpl.php:45 | ||
1035 | #: tmp/page.footer.cedf684561d925457130839629000a81.rtpl.php:45 | ||
1036 | msgid "Expand all" | ||
1037 | msgstr "すべて展開する" | ||
1038 | |||
1039 | #: tmp/page.footer.b91ef64efc3688266305ea9b42e5017e.rtpl.php:46 | ||
1040 | #: tmp/page.footer.cedf684561d925457130839629000a81.rtpl.php:46 | ||
1041 | msgid "Are you sure you want to delete this link?" | ||
1042 | msgstr "本当にこのリンクを削除しますか?" | ||
1043 | |||
1044 | #: tmp/page.header.b91ef64efc3688266305ea9b42e5017e.rtpl.php:61 | ||
1045 | #: tmp/page.header.b91ef64efc3688266305ea9b42e5017e.rtpl.php:86 | ||
1046 | #: tmp/page.header.cedf684561d925457130839629000a81.rtpl.php:61 | ||
1047 | #: tmp/page.header.cedf684561d925457130839629000a81.rtpl.php:86 | ||
1048 | msgid "RSS Feed" | ||
1049 | msgstr "RSS フィード" | ||
1050 | |||
1051 | #: tmp/page.header.b91ef64efc3688266305ea9b42e5017e.rtpl.php:66 | ||
1052 | #: tmp/page.header.b91ef64efc3688266305ea9b42e5017e.rtpl.php:102 | ||
1053 | #: tmp/page.header.cedf684561d925457130839629000a81.rtpl.php:66 | ||
1054 | #: tmp/page.header.cedf684561d925457130839629000a81.rtpl.php:102 | ||
1055 | msgid "Logout" | ||
1056 | msgstr "ログアウト" | ||
1057 | |||
1058 | #: tmp/page.header.b91ef64efc3688266305ea9b42e5017e.rtpl.php:169 | ||
1059 | #: tmp/page.header.cedf684561d925457130839629000a81.rtpl.php:169 | ||
1060 | msgid "is available" | ||
1061 | msgstr "が利用可能" | ||
1062 | |||
1063 | #: tmp/page.header.b91ef64efc3688266305ea9b42e5017e.rtpl.php:176 | ||
1064 | #: tmp/page.header.cedf684561d925457130839629000a81.rtpl.php:176 | ||
1065 | msgid "Error" | ||
1066 | msgstr "エラー" | ||
1067 | |||
1068 | #: tmp/picwall.b91ef64efc3688266305ea9b42e5017e.rtpl.php:16 | ||
1069 | msgid "Picture Wall" | ||
1070 | msgstr "ピクチャーウォール" | ||
1071 | |||
1072 | #: tmp/picwall.b91ef64efc3688266305ea9b42e5017e.rtpl.php:16 | ||
1073 | msgid "pics" | ||
1074 | msgstr "画像" | ||
1075 | |||
1076 | #: tmp/pluginsadmin.b91ef64efc3688266305ea9b42e5017e.rtpl.php:15 | ||
1077 | msgid "You need to enable Javascript to change plugin loading order." | ||
1078 | msgstr "" | ||
1079 | "プラグインを読み込む順番を変更するには、Javascriptを有効にする必要がありま" | ||
1080 | "す。" | ||
1081 | |||
1082 | #: tmp/pluginsadmin.b91ef64efc3688266305ea9b42e5017e.rtpl.php:29 | ||
1083 | msgid "Enabled Plugins" | ||
1084 | msgstr "有効なプラグイン" | ||
1085 | |||
1086 | #: tmp/pluginsadmin.b91ef64efc3688266305ea9b42e5017e.rtpl.php:34 | ||
1087 | #: tmp/pluginsadmin.b91ef64efc3688266305ea9b42e5017e.rtpl.php:155 | ||
1088 | msgid "No plugin enabled." | ||
1089 | msgstr "有効なプラグインはありません。" | ||
1090 | |||
1091 | #: tmp/pluginsadmin.b91ef64efc3688266305ea9b42e5017e.rtpl.php:40 | ||
1092 | #: tmp/pluginsadmin.b91ef64efc3688266305ea9b42e5017e.rtpl.php:73 | ||
1093 | msgid "Disable" | ||
1094 | msgstr "無効化" | ||
1095 | |||
1096 | #: tmp/pluginsadmin.b91ef64efc3688266305ea9b42e5017e.rtpl.php:41 | ||
1097 | #: tmp/pluginsadmin.b91ef64efc3688266305ea9b42e5017e.rtpl.php:74 | ||
1098 | #: tmp/pluginsadmin.b91ef64efc3688266305ea9b42e5017e.rtpl.php:98 | ||
1099 | #: tmp/pluginsadmin.b91ef64efc3688266305ea9b42e5017e.rtpl.php:123 | ||
1100 | msgid "Name" | ||
1101 | msgstr "名前" | ||
1102 | |||
1103 | #: tmp/pluginsadmin.b91ef64efc3688266305ea9b42e5017e.rtpl.php:43 | ||
1104 | #: tmp/pluginsadmin.b91ef64efc3688266305ea9b42e5017e.rtpl.php:76 | ||
1105 | msgid "Order" | ||
1106 | msgstr "順序" | ||
1107 | |||
1108 | #: tmp/pluginsadmin.b91ef64efc3688266305ea9b42e5017e.rtpl.php:86 | ||
1109 | msgid "Disabled Plugins" | ||
1110 | msgstr "無効なプラグイン" | ||
1111 | |||
1112 | #: tmp/pluginsadmin.b91ef64efc3688266305ea9b42e5017e.rtpl.php:91 | ||
1113 | msgid "No plugin disabled." | ||
1114 | msgstr "無効なプラグインはありません。" | ||
1115 | |||
1116 | #: tmp/pluginsadmin.b91ef64efc3688266305ea9b42e5017e.rtpl.php:97 | ||
1117 | #: tmp/pluginsadmin.b91ef64efc3688266305ea9b42e5017e.rtpl.php:122 | ||
1118 | msgid "Enable" | ||
1119 | msgstr "有効化" | ||
1120 | |||
1121 | #: tmp/pluginsadmin.b91ef64efc3688266305ea9b42e5017e.rtpl.php:134 | ||
1122 | msgid "More plugins available" | ||
1123 | msgstr "さらに利用できるプラグインがあります" | ||
1124 | |||
1125 | #: tmp/pluginsadmin.b91ef64efc3688266305ea9b42e5017e.rtpl.php:136 | ||
1126 | msgid "in the documentation" | ||
1127 | msgstr "ドキュメント内" | ||
1128 | |||
1129 | #: tmp/pluginsadmin.b91ef64efc3688266305ea9b42e5017e.rtpl.php:150 | ||
1130 | msgid "Plugin configuration" | ||
1131 | msgstr "プラグイン設定" | ||
1132 | |||
1133 | #: tmp/pluginsadmin.b91ef64efc3688266305ea9b42e5017e.rtpl.php:195 | ||
1134 | msgid "No parameter available." | ||
1135 | msgstr "利用可能な設定項目はありません。" | ||
1136 | |||
1137 | #: tmp/tag.cloud.b91ef64efc3688266305ea9b42e5017e.rtpl.php:19 | ||
1138 | #: tmp/tag.list.b91ef64efc3688266305ea9b42e5017e.rtpl.php:19 | ||
1139 | msgid "tags" | ||
1140 | msgstr "タグ" | ||
1141 | |||
1142 | #: tmp/tag.cloud.b91ef64efc3688266305ea9b42e5017e.rtpl.php:24 | ||
1143 | #: tmp/tag.list.b91ef64efc3688266305ea9b42e5017e.rtpl.php:24 | ||
1144 | msgid "List all links with those tags" | ||
1145 | msgstr "このタグが付いているリンクをリスト化する" | ||
1146 | |||
1147 | #: tmp/tag.sort.b91ef64efc3688266305ea9b42e5017e.rtpl.php:3 | ||
1148 | #: tmp/tag.sort.cedf684561d925457130839629000a81.rtpl.php:3 | ||
1149 | msgid "Sort by:" | ||
1150 | msgstr "分類:" | ||
1151 | |||
1152 | #: tmp/tag.sort.b91ef64efc3688266305ea9b42e5017e.rtpl.php:5 | ||
1153 | #: tmp/tag.sort.cedf684561d925457130839629000a81.rtpl.php:5 | ||
1154 | msgid "Cloud" | ||
1155 | msgstr "クラウド" | ||
1156 | |||
1157 | #: tmp/tag.sort.b91ef64efc3688266305ea9b42e5017e.rtpl.php:6 | ||
1158 | #: tmp/tag.sort.cedf684561d925457130839629000a81.rtpl.php:6 | ||
1159 | msgid "Most used" | ||
1160 | msgstr "もっとも使われた" | ||
1161 | |||
1162 | #: tmp/tag.sort.b91ef64efc3688266305ea9b42e5017e.rtpl.php:7 | ||
1163 | #: tmp/tag.sort.cedf684561d925457130839629000a81.rtpl.php:7 | ||
1164 | msgid "Alphabetical" | ||
1165 | msgstr "アルファベット順" | ||
1166 | |||
1167 | #: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:14 | ||
1168 | msgid "Settings" | ||
1169 | msgstr "設定" | ||
1170 | |||
1171 | #: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:16 | ||
1172 | msgid "Change Shaarli settings: title, timezone, etc." | ||
1173 | msgstr "Shaarli の設定を変更: タイトル、タイムゾーンなど。" | ||
1174 | |||
1175 | #: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:17 | ||
1176 | msgid "Configure your Shaarli" | ||
1177 | msgstr "あなたの Shaarli を設定" | ||
1178 | |||
1179 | #: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:21 | ||
1180 | msgid "Enable, disable and configure plugins" | ||
1181 | msgstr "プラグインを有効化、無効化、設定する" | ||
1182 | |||
1183 | #: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:28 | ||
1184 | msgid "Change your password" | ||
1185 | msgstr "パスワードを変更" | ||
1186 | |||
1187 | #: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:35 | ||
1188 | msgid "Rename or delete a tag in all links" | ||
1189 | msgstr "すべてのリンクのタグの名前を変更する、または削除する" | ||
1190 | |||
1191 | #: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:41 | ||
1192 | msgid "" | ||
1193 | "Import Netscape HTML bookmarks (as exported from Firefox, Chrome, Opera, " | ||
1194 | "delicious...)" | ||
1195 | msgstr "" | ||
1196 | "Netscape HTML 形式のブックマークをインポートする (Firefox、Chrome、Operaと" | ||
1197 | "いったブラウザーが含まれます)" | ||
1198 | |||
1199 | #: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:42 | ||
1200 | msgid "Import links" | ||
1201 | msgstr "リンクをインポート" | ||
1202 | |||
1203 | #: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:47 | ||
1204 | msgid "" | ||
1205 | "Export Netscape HTML bookmarks (which can be imported in Firefox, Chrome, " | ||
1206 | "Opera, delicious...)" | ||
1207 | msgstr "" | ||
1208 | "Netscape HTML 形式のブックマークをエクスポートする (Firefox、Chrome、Operaと" | ||
1209 | "いったブラウザーが含まれます)" | ||
1210 | |||
1211 | #: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:48 | ||
1212 | msgid "Export database" | ||
1213 | msgstr "リンクをエクスポート" | ||
1214 | |||
1215 | #: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:71 | ||
1216 | msgid "" | ||
1217 | "Drag one of these button to your bookmarks toolbar or right-click it and " | ||
1218 | "\"Bookmark This Link\"" | ||
1219 | msgstr "" | ||
1220 | "これらのボタンのうち1つををブックマークバーにドラッグするか、右クリックして" | ||
1221 | "「このリンクをブックマークに追加」してください" | ||
1222 | |||
1223 | #: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:72 | ||
1224 | msgid "then click on the bookmarklet in any page you want to share." | ||
1225 | msgstr "共有したいページでブックマークレットをクリックしてください。" | ||
1226 | |||
1227 | #: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:76 | ||
1228 | #: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:100 | ||
1229 | msgid "" | ||
1230 | "Drag this link to your bookmarks toolbar or right-click it and Bookmark This " | ||
1231 | "Link" | ||
1232 | msgstr "" | ||
1233 | "このリンクをブックマークバーにドラッグするか、右クリックして「このリンクを" | ||
1234 | "ブックマークに追加」してください" | ||
1235 | |||
1236 | #: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:77 | ||
1237 | msgid "then click ✚Shaare link button in any page you want to share" | ||
1238 | msgstr "✚リンクを共有 ボタンをクリックすることで、どこでもリンクを共有できます" | ||
1239 | |||
1240 | #: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:86 | ||
1241 | #: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:108 | ||
1242 | msgid "The selected text is too long, it will be truncated." | ||
1243 | msgstr "選択された文字列は長すぎるので、一部が切り捨てられます。" | ||
1244 | |||
1245 | #: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:96 | ||
1246 | msgid "Shaare link" | ||
1247 | msgstr "共有リンク" | ||
1248 | |||
1249 | #: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:101 | ||
1250 | msgid "" | ||
1251 | "Then click ✚Add Note button anytime to start composing a private Note (text " | ||
1252 | "post) to your Shaarli" | ||
1253 | msgstr "" | ||
1254 | "✚ノートを追加 ボタンをクリックすることで、いつでもプライベートノート(テキスト" | ||
1255 | "形式)をShaarli上に作成できます" | ||
1256 | |||
1257 | #: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:117 | ||
1258 | msgid "Add Note" | ||
1259 | msgstr "ノートを追加" | ||
1260 | |||
1261 | #: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:129 | ||
1262 | msgid "" | ||
1263 | "You need to browse your Shaarli over <strong>HTTPS</strong> to use this " | ||
1264 | "functionality." | ||
1265 | msgstr "" | ||
1266 | "この機能を使用するには、<strong>HTTPS</strong> 経由でShaarliに接続してくださ" | ||
1267 | "い。" | ||
1268 | |||
1269 | #: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:134 | ||
1270 | msgid "Add to" | ||
1271 | msgstr "次に追加:" | ||
1272 | |||
1273 | #: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:145 | ||
1274 | msgid "3rd party" | ||
1275 | msgstr "サードパーティー" | ||
1276 | |||
1277 | #: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:147 | ||
1278 | #: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:153 | ||
1279 | msgid "Plugin" | ||
1280 | msgstr "プラグイン" | ||
1281 | |||
1282 | #: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:148 | ||
1283 | #: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:154 | ||
1284 | msgid "plugin" | ||
1285 | msgstr "プラグイン" | ||
1286 | |||
1287 | #: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:175 | ||
1288 | msgid "" | ||
1289 | "Drag this link to your bookmarks toolbar, or right-click it and choose " | ||
1290 | "Bookmark This Link" | ||
1291 | msgstr "" | ||
1292 | "このリンクをブックマークバーにドラッグするか、右クリックして「このリンクを" | ||
1293 | "ブックマークに追加」してください" | ||
@@ -61,29 +61,31 @@ require_once 'application/FileUtils.php'; | |||
61 | require_once 'application/TimeZone.php'; | 61 | require_once 'application/TimeZone.php'; |
62 | require_once 'application/Utils.php'; | 62 | require_once 'application/Utils.php'; |
63 | 63 | ||
64 | use \Shaarli\ApplicationUtils; | 64 | use Shaarli\ApplicationUtils; |
65 | use Shaarli\Bookmark\BookmarkServiceInterface; | ||
66 | use \Shaarli\Bookmark\Exception\BookmarkNotFoundException; | ||
67 | use Shaarli\Bookmark\Bookmark; | 65 | use Shaarli\Bookmark\Bookmark; |
68 | use Shaarli\Bookmark\BookmarkFilter; | ||
69 | use Shaarli\Bookmark\BookmarkFileService; | 66 | use Shaarli\Bookmark\BookmarkFileService; |
70 | use \Shaarli\Config\ConfigManager; | 67 | use Shaarli\Bookmark\BookmarkFilter; |
71 | use \Shaarli\Feed\CachedPage; | 68 | use Shaarli\Bookmark\BookmarkServiceInterface; |
72 | use \Shaarli\Feed\FeedBuilder; | 69 | use Shaarli\Bookmark\Exception\BookmarkNotFoundException; |
70 | use Shaarli\Config\ConfigManager; | ||
71 | use Shaarli\Container\ContainerBuilder; | ||
72 | use Shaarli\Feed\CachedPage; | ||
73 | use Shaarli\Feed\FeedBuilder; | ||
73 | use Shaarli\Formatter\BookmarkMarkdownFormatter; | 74 | use Shaarli\Formatter\BookmarkMarkdownFormatter; |
74 | use Shaarli\Formatter\FormatterFactory; | 75 | use Shaarli\Formatter\FormatterFactory; |
75 | use \Shaarli\History; | 76 | use Shaarli\History; |
76 | use \Shaarli\Languages; | 77 | use Shaarli\Languages; |
77 | use \Shaarli\Netscape\NetscapeBookmarkUtils; | 78 | use Shaarli\Netscape\NetscapeBookmarkUtils; |
78 | use \Shaarli\Plugin\PluginManager; | 79 | use Shaarli\Plugin\PluginManager; |
79 | use \Shaarli\Render\PageBuilder; | 80 | use Shaarli\Render\PageBuilder; |
80 | use \Shaarli\Render\ThemeUtils; | 81 | use Shaarli\Render\ThemeUtils; |
81 | use \Shaarli\Router; | 82 | use Shaarli\Router; |
82 | use \Shaarli\Security\LoginManager; | 83 | use Shaarli\Security\LoginManager; |
83 | use \Shaarli\Security\SessionManager; | 84 | use Shaarli\Security\SessionManager; |
84 | use \Shaarli\Thumbnailer; | 85 | use Shaarli\Thumbnailer; |
85 | use \Shaarli\Updater\Updater; | 86 | use Shaarli\Updater\Updater; |
86 | use \Shaarli\Updater\UpdaterUtils; | 87 | use Shaarli\Updater\UpdaterUtils; |
88 | use Slim\App; | ||
87 | 89 | ||
88 | // Ensure the PHP version is supported | 90 | // Ensure the PHP version is supported |
89 | try { | 91 | try { |
@@ -243,12 +245,14 @@ if (isset($_POST['login'])) { | |||
243 | } | 245 | } |
244 | 246 | ||
245 | // Send cookie with the new expiration date to the browser | 247 | // Send cookie with the new expiration date to the browser |
248 | session_destroy(); | ||
246 | session_set_cookie_params($expirationTime, $cookiedir, $_SERVER['SERVER_NAME']); | 249 | session_set_cookie_params($expirationTime, $cookiedir, $_SERVER['SERVER_NAME']); |
250 | session_start(); | ||
247 | session_regenerate_id(true); | 251 | session_regenerate_id(true); |
248 | 252 | ||
249 | // Optional redirect after login: | 253 | // Optional redirect after login: |
250 | if (isset($_GET['post'])) { | 254 | if (isset($_GET['post'])) { |
251 | $uri = '?post='. urlencode($_GET['post']); | 255 | $uri = './?post='. urlencode($_GET['post']); |
252 | foreach (array('description', 'source', 'title', 'tags') as $param) { | 256 | foreach (array('description', 'source', 'title', 'tags') as $param) { |
253 | if (!empty($_GET[$param])) { | 257 | if (!empty($_GET[$param])) { |
254 | $uri .= '&'.$param.'='.urlencode($_GET[$param]); | 258 | $uri .= '&'.$param.'='.urlencode($_GET[$param]); |
@@ -259,22 +263,22 @@ if (isset($_POST['login'])) { | |||
259 | } | 263 | } |
260 | 264 | ||
261 | if (isset($_GET['edit_link'])) { | 265 | if (isset($_GET['edit_link'])) { |
262 | header('Location: ?edit_link='. escape($_GET['edit_link'])); | 266 | header('Location: ./?edit_link='. escape($_GET['edit_link'])); |
263 | exit; | 267 | exit; |
264 | } | 268 | } |
265 | 269 | ||
266 | if (isset($_POST['returnurl'])) { | 270 | if (isset($_POST['returnurl'])) { |
267 | // Prevent loops over login screen. | 271 | // Prevent loops over login screen. |
268 | if (strpos($_POST['returnurl'], 'do=login') === false) { | 272 | if (strpos($_POST['returnurl'], '/login') === false) { |
269 | header('Location: '. generateLocation($_POST['returnurl'], $_SERVER['HTTP_HOST'])); | 273 | header('Location: '. generateLocation($_POST['returnurl'], $_SERVER['HTTP_HOST'])); |
270 | exit; | 274 | exit; |
271 | } | 275 | } |
272 | } | 276 | } |
273 | header('Location: ?'); | 277 | header('Location: ./?'); |
274 | exit; | 278 | exit; |
275 | } else { | 279 | } else { |
276 | $loginManager->handleFailedLogin($_SERVER); | 280 | $loginManager->handleFailedLogin($_SERVER); |
277 | $redir = '&username='. urlencode($_POST['login']); | 281 | $redir = '?username='. urlencode($_POST['login']); |
278 | if (isset($_GET['post'])) { | 282 | if (isset($_GET['post'])) { |
279 | $redir .= '&post=' . urlencode($_GET['post']); | 283 | $redir .= '&post=' . urlencode($_GET['post']); |
280 | foreach (array('description', 'source', 'title', 'tags') as $param) { | 284 | foreach (array('description', 'source', 'title', 'tags') as $param) { |
@@ -284,7 +288,7 @@ if (isset($_POST['login'])) { | |||
284 | } | 288 | } |
285 | } | 289 | } |
286 | // Redirect to login screen. | 290 | // Redirect to login screen. |
287 | echo '<script>alert("'. t("Wrong login/password.") .'");document.location=\'?do=login'.$redir.'\';</script>'; | 291 | echo '<script>alert("'. t("Wrong login/password.") .'");document.location=\'./login'.$redir.'\';</script>'; |
288 | exit; | 292 | exit; |
289 | } | 293 | } |
290 | } | 294 | } |
@@ -592,19 +596,7 @@ function renderPage($conf, $pluginManager, $bookmarkService, $history, $sessionM | |||
592 | 596 | ||
593 | // -------- Display login form. | 597 | // -------- Display login form. |
594 | if ($targetPage == Router::$PAGE_LOGIN) { | 598 | if ($targetPage == Router::$PAGE_LOGIN) { |
595 | if ($conf->get('security.open_shaarli')) { | 599 | header('Location: ./login'); |
596 | header('Location: ?'); | ||
597 | exit; | ||
598 | } // No need to login for open Shaarli | ||
599 | if (isset($_GET['username'])) { | ||
600 | $PAGE->assign('username', escape($_GET['username'])); | ||
601 | } | ||
602 | $PAGE->assign('returnurl', (isset($_SERVER['HTTP_REFERER']) ? escape($_SERVER['HTTP_REFERER']):'')); | ||
603 | // add default state of the 'remember me' checkbox | ||
604 | $PAGE->assign('remember_user_default', $conf->get('privacy.remember_user_default')); | ||
605 | $PAGE->assign('user_can_login', $loginManager->canLogin($_SERVER)); | ||
606 | $PAGE->assign('pagetitle', t('Login') .' - '. $conf->get('general.title', 'Shaarli')); | ||
607 | $PAGE->renderPage('loginform'); | ||
608 | exit; | 600 | exit; |
609 | } | 601 | } |
610 | // -------- User wants to logout. | 602 | // -------- User wants to logout. |
@@ -667,6 +659,7 @@ function renderPage($conf, $pluginManager, $bookmarkService, $history, $sessionM | |||
667 | 659 | ||
668 | alphabetical_sort($tags, false, true); | 660 | alphabetical_sort($tags, false, true); |
669 | 661 | ||
662 | $logMaxCount = $maxcount > 1 ? log($maxcount, 30) : 1; | ||
670 | $tagList = array(); | 663 | $tagList = array(); |
671 | foreach ($tags as $key => $value) { | 664 | foreach ($tags as $key => $value) { |
672 | if (in_array($key, $filteringTags)) { | 665 | if (in_array($key, $filteringTags)) { |
@@ -674,8 +667,8 @@ function renderPage($conf, $pluginManager, $bookmarkService, $history, $sessionM | |||
674 | } | 667 | } |
675 | // Tag font size scaling: | 668 | // Tag font size scaling: |
676 | // default 15 and 30 logarithm bases affect scaling, | 669 | // default 15 and 30 logarithm bases affect scaling, |
677 | // 22 and 6 are arbitrary font sizes for max and min sizes. | 670 | // 2.2 and 0.8 are arbitrary font sizes in em. |
678 | $size = log($value, 15) / log($maxcount, 30) * 2.2 + 0.8; | 671 | $size = log($value, 15) / $logMaxCount * 2.2 + 0.8; |
679 | $tagList[$key] = array( | 672 | $tagList[$key] = array( |
680 | 'count' => $value, | 673 | 'count' => $value, |
681 | 'size' => number_format($size, 2, '.', ''), | 674 | 'size' => number_format($size, 2, '.', ''), |
@@ -931,7 +924,7 @@ function renderPage($conf, $pluginManager, $bookmarkService, $history, $sessionM | |||
931 | // Show login screen, then redirect to ?post=... | 924 | // Show login screen, then redirect to ?post=... |
932 | if (isset($_GET['post'])) { | 925 | if (isset($_GET['post'])) { |
933 | header( // Redirect to login page, then back to post link. | 926 | header( // Redirect to login page, then back to post link. |
934 | 'Location: ?do=login&post='.urlencode($_GET['post']). | 927 | 'Location: /login?post='.urlencode($_GET['post']). |
935 | (!empty($_GET['title'])?'&title='.urlencode($_GET['title']):''). | 928 | (!empty($_GET['title'])?'&title='.urlencode($_GET['title']):''). |
936 | (!empty($_GET['description'])?'&description='.urlencode($_GET['description']):''). | 929 | (!empty($_GET['description'])?'&description='.urlencode($_GET['description']):''). |
937 | (!empty($_GET['tags'])?'&tags='.urlencode($_GET['tags']):''). | 930 | (!empty($_GET['tags'])?'&tags='.urlencode($_GET['tags']):''). |
@@ -942,7 +935,7 @@ function renderPage($conf, $pluginManager, $bookmarkService, $history, $sessionM | |||
942 | 935 | ||
943 | showLinkList($PAGE, $bookmarkService, $conf, $pluginManager, $loginManager); | 936 | showLinkList($PAGE, $bookmarkService, $conf, $pluginManager, $loginManager); |
944 | if (isset($_GET['edit_link'])) { | 937 | if (isset($_GET['edit_link'])) { |
945 | header('Location: ?do=login&edit_link='. escape($_GET['edit_link'])); | 938 | header('Location: /login?edit_link='. escape($_GET['edit_link'])); |
946 | exit; | 939 | exit; |
947 | } | 940 | } |
948 | 941 | ||
@@ -1898,7 +1891,7 @@ function install($conf, $sessionManager, $loginManager) | |||
1898 | echo '<script>alert(' | 1891 | echo '<script>alert(' |
1899 | .'"Shaarli is now configured. ' | 1892 | .'"Shaarli is now configured. ' |
1900 | .'Please enter your login/password and start shaaring your bookmarks!"' | 1893 | .'Please enter your login/password and start shaaring your bookmarks!"' |
1901 | .');document.location=\'?do=login\';</script>'; | 1894 | .');document.location=\'./login\';</script>'; |
1902 | exit; | 1895 | exit; |
1903 | } | 1896 | } |
1904 | 1897 | ||
@@ -1928,20 +1921,18 @@ if (isset($_SERVER['QUERY_STRING']) && startsWith($_SERVER['QUERY_STRING'], 'do= | |||
1928 | exit; | 1921 | exit; |
1929 | } | 1922 | } |
1930 | 1923 | ||
1931 | $container = new \Slim\Container(); | 1924 | $containerBuilder = new ContainerBuilder($conf, $sessionManager, $loginManager); |
1932 | $container['conf'] = $conf; | 1925 | $container = $containerBuilder->build(); |
1933 | $container['plugins'] = $pluginManager; | 1926 | $app = new App($container); |
1934 | $container['history'] = $history; | ||
1935 | $app = new \Slim\App($container); | ||
1936 | 1927 | ||
1937 | // REST API routes | 1928 | // REST API routes |
1938 | $app->group('/api/v1', function () { | 1929 | $app->group('/api/v1', function () { |
1939 | $this->get('/info', '\Shaarli\Api\Controllers\Info:getInfo')->setName('getInfo'); | 1930 | $this->get('/info', '\Shaarli\Api\Controllers\Info:getInfo')->setName('getInfo'); |
1940 | $this->get('/bookmarks', '\Shaarli\Api\Controllers\Links:getLinks')->setName('getLinks'); | 1931 | $this->get('/links', '\Shaarli\Api\Controllers\Links:getLinks')->setName('getLinks'); |
1941 | $this->get('/bookmarks/{id:[\d]+}', '\Shaarli\Api\Controllers\Links:getLink')->setName('getLink'); | 1932 | $this->get('/links/{id:[\d]+}', '\Shaarli\Api\Controllers\Links:getLink')->setName('getLink'); |
1942 | $this->post('/bookmarks', '\Shaarli\Api\Controllers\Links:postLink')->setName('postLink'); | 1933 | $this->post('/links', '\Shaarli\Api\Controllers\Links:postLink')->setName('postLink'); |
1943 | $this->put('/bookmarks/{id:[\d]+}', '\Shaarli\Api\Controllers\Links:putLink')->setName('putLink'); | 1934 | $this->put('/links/{id:[\d]+}', '\Shaarli\Api\Controllers\Links:putLink')->setName('putLink'); |
1944 | $this->delete('/bookmarks/{id:[\d]+}', '\Shaarli\Api\Controllers\Links:deleteLink')->setName('deleteLink'); | 1935 | $this->delete('/links/{id:[\d]+}', '\Shaarli\Api\Controllers\Links:deleteLink')->setName('deleteLink'); |
1945 | 1936 | ||
1946 | $this->get('/tags', '\Shaarli\Api\Controllers\Tags:getTags')->setName('getTags'); | 1937 | $this->get('/tags', '\Shaarli\Api\Controllers\Tags:getTags')->setName('getTags'); |
1947 | $this->get('/tags/{tagName:[\w]+}', '\Shaarli\Api\Controllers\Tags:getTag')->setName('getTag'); | 1938 | $this->get('/tags/{tagName:[\w]+}', '\Shaarli\Api\Controllers\Tags:getTag')->setName('getTag'); |
@@ -1951,6 +1942,10 @@ $app->group('/api/v1', function () { | |||
1951 | $this->get('/history', '\Shaarli\Api\Controllers\HistoryController:getHistory')->setName('getHistory'); | 1942 | $this->get('/history', '\Shaarli\Api\Controllers\HistoryController:getHistory')->setName('getHistory'); |
1952 | })->add('\Shaarli\Api\ApiMiddleware'); | 1943 | })->add('\Shaarli\Api\ApiMiddleware'); |
1953 | 1944 | ||
1945 | $app->group('', function () { | ||
1946 | $this->get('/login', '\Shaarli\Front\Controller\LoginController:index')->setName('login'); | ||
1947 | })->add('\Shaarli\Front\ShaarliMiddleware'); | ||
1948 | |||
1954 | $response = $app->run(true); | 1949 | $response = $app->run(true); |
1955 | 1950 | ||
1956 | // Hack to make Slim and Shaarli router work together: | 1951 | // 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 | |||
203 | public function testGenerateLocationLoop() | 203 | public function testGenerateLocationLoop() |
204 | { | 204 | { |
205 | $ref = 'http://localhost/?test'; | 205 | $ref = 'http://localhost/?test'; |
206 | $this->assertEquals('?', generateLocation($ref, 'localhost', array('test'))); | 206 | $this->assertEquals('./?', generateLocation($ref, 'localhost', array('test'))); |
207 | } | 207 | } |
208 | 208 | ||
209 | /** | 209 | /** |
@@ -212,7 +212,7 @@ class UtilsTest extends PHPUnit\Framework\TestCase | |||
212 | public function testGenerateLocationOut() | 212 | public function testGenerateLocationOut() |
213 | { | 213 | { |
214 | $ref = 'http://somewebsite.com/?test'; | 214 | $ref = 'http://somewebsite.com/?test'; |
215 | $this->assertEquals('?', generateLocation($ref, 'localhost')); | 215 | $this->assertEquals('./?', generateLocation($ref, 'localhost')); |
216 | } | 216 | } |
217 | 217 | ||
218 | 218 | ||
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 @@ | |||
1 | <?php | ||
2 | |||
3 | declare(strict_types=1); | ||
4 | |||
5 | namespace Shaarli\Container; | ||
6 | |||
7 | use PHPUnit\Framework\TestCase; | ||
8 | use Shaarli\Bookmark\BookmarkServiceInterface; | ||
9 | use Shaarli\Config\ConfigManager; | ||
10 | use Shaarli\History; | ||
11 | use Shaarli\Render\PageBuilder; | ||
12 | use Shaarli\Security\LoginManager; | ||
13 | use Shaarli\Security\SessionManager; | ||
14 | |||
15 | class ContainerBuilderTest extends TestCase | ||
16 | { | ||
17 | /** @var ConfigManager */ | ||
18 | protected $conf; | ||
19 | |||
20 | /** @var SessionManager */ | ||
21 | protected $sessionManager; | ||
22 | |||
23 | /** @var LoginManager */ | ||
24 | protected $loginManager; | ||
25 | |||
26 | /** @var ContainerBuilder */ | ||
27 | protected $containerBuilder; | ||
28 | |||
29 | public function setUp(): void | ||
30 | { | ||
31 | $this->conf = new ConfigManager('tests/utils/config/configJson'); | ||
32 | $this->sessionManager = $this->createMock(SessionManager::class); | ||
33 | $this->loginManager = $this->createMock(LoginManager::class); | ||
34 | |||
35 | $this->containerBuilder = new ContainerBuilder($this->conf, $this->sessionManager, $this->loginManager); | ||
36 | } | ||
37 | |||
38 | public function testBuildContainer(): void | ||
39 | { | ||
40 | $container = $this->containerBuilder->build(); | ||
41 | |||
42 | static::assertInstanceOf(ConfigManager::class, $container->conf); | ||
43 | static::assertInstanceOf(SessionManager::class, $container->sessionManager); | ||
44 | static::assertInstanceOf(LoginManager::class, $container->loginManager); | ||
45 | static::assertInstanceOf(History::class, $container->history); | ||
46 | static::assertInstanceOf(BookmarkServiceInterface::class, $container->bookmarkService); | ||
47 | static::assertInstanceOf(PageBuilder::class, $container->pageBuilder); | ||
48 | } | ||
49 | } | ||
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 @@ | |||
1 | <?php | ||
2 | |||
3 | declare(strict_types=1); | ||
4 | |||
5 | namespace Shaarli\Front; | ||
6 | |||
7 | use PHPUnit\Framework\TestCase; | ||
8 | use Shaarli\Config\ConfigManager; | ||
9 | use Shaarli\Container\ShaarliContainer; | ||
10 | use Shaarli\Front\Exception\LoginBannedException; | ||
11 | use Shaarli\Render\PageBuilder; | ||
12 | use Slim\Http\Request; | ||
13 | use Slim\Http\Response; | ||
14 | |||
15 | class ShaarliMiddlewareTest extends TestCase | ||
16 | { | ||
17 | /** @var ShaarliContainer */ | ||
18 | protected $container; | ||
19 | |||
20 | /** @var ShaarliMiddleware */ | ||
21 | protected $middleware; | ||
22 | |||
23 | public function setUp(): void | ||
24 | { | ||
25 | $this->container = $this->createMock(ShaarliContainer::class); | ||
26 | $this->middleware = new ShaarliMiddleware($this->container); | ||
27 | } | ||
28 | |||
29 | public function testMiddlewareExecution(): void | ||
30 | { | ||
31 | $request = $this->createMock(Request::class); | ||
32 | $response = new Response(); | ||
33 | $controller = function (Request $request, Response $response): Response { | ||
34 | return $response->withStatus(418); // I'm a tea pot | ||
35 | }; | ||
36 | |||
37 | /** @var Response $result */ | ||
38 | $result = $this->middleware->__invoke($request, $response, $controller); | ||
39 | |||
40 | static::assertInstanceOf(Response::class, $result); | ||
41 | static::assertSame(418, $result->getStatusCode()); | ||
42 | } | ||
43 | |||
44 | public function testMiddlewareExecutionWithException(): void | ||
45 | { | ||
46 | $request = $this->createMock(Request::class); | ||
47 | $response = new Response(); | ||
48 | $controller = function (): void { | ||
49 | $exception = new LoginBannedException(); | ||
50 | |||
51 | throw new $exception; | ||
52 | }; | ||
53 | |||
54 | $pageBuilder = $this->createMock(PageBuilder::class); | ||
55 | $pageBuilder->method('render')->willReturnCallback(function (string $message): string { | ||
56 | return $message; | ||
57 | }); | ||
58 | $this->container->pageBuilder = $pageBuilder; | ||
59 | |||
60 | $conf = $this->createMock(ConfigManager::class); | ||
61 | $this->container->conf = $conf; | ||
62 | |||
63 | /** @var Response $result */ | ||
64 | $result = $this->middleware->__invoke($request, $response, $controller); | ||
65 | |||
66 | static::assertInstanceOf(Response::class, $result); | ||
67 | static::assertSame(401, $result->getStatusCode()); | ||
68 | static::assertContains('error', (string) $result->getBody()); | ||
69 | } | ||
70 | } | ||
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 @@ | |||
1 | <?php | ||
2 | |||
3 | declare(strict_types=1); | ||
4 | |||
5 | namespace Shaarli\Front\Controller; | ||
6 | |||
7 | use PHPUnit\Framework\TestCase; | ||
8 | use Shaarli\Bookmark\BookmarkServiceInterface; | ||
9 | use Shaarli\Config\ConfigManager; | ||
10 | use Shaarli\Container\ShaarliContainer; | ||
11 | use Shaarli\Front\Exception\LoginBannedException; | ||
12 | use Shaarli\Plugin\PluginManager; | ||
13 | use Shaarli\Render\PageBuilder; | ||
14 | use Shaarli\Security\LoginManager; | ||
15 | use Slim\Http\Request; | ||
16 | use Slim\Http\Response; | ||
17 | |||
18 | class LoginControllerTest extends TestCase | ||
19 | { | ||
20 | /** @var ShaarliContainer */ | ||
21 | protected $container; | ||
22 | |||
23 | /** @var LoginController */ | ||
24 | protected $controller; | ||
25 | |||
26 | public function setUp(): void | ||
27 | { | ||
28 | $this->container = $this->createMock(ShaarliContainer::class); | ||
29 | $this->controller = new LoginController($this->container); | ||
30 | } | ||
31 | |||
32 | public function testValidControllerInvoke(): void | ||
33 | { | ||
34 | $this->createValidContainerMockSet(); | ||
35 | |||
36 | $request = $this->createMock(Request::class); | ||
37 | $request->expects(static::once())->method('getServerParam')->willReturn('> referer'); | ||
38 | $response = new Response(); | ||
39 | |||
40 | $assignedVariables = []; | ||
41 | $this->container->pageBuilder | ||
42 | ->method('assign') | ||
43 | ->willReturnCallback(function ($key, $value) use (&$assignedVariables) { | ||
44 | $assignedVariables[$key] = $value; | ||
45 | |||
46 | return $this; | ||
47 | }) | ||
48 | ; | ||
49 | |||
50 | $result = $this->controller->index($request, $response); | ||
51 | |||
52 | static::assertInstanceOf(Response::class, $result); | ||
53 | static::assertSame(200, $result->getStatusCode()); | ||
54 | static::assertSame('loginform', (string) $result->getBody()); | ||
55 | |||
56 | static::assertSame('> referer', $assignedVariables['returnurl']); | ||
57 | static::assertSame(true, $assignedVariables['remember_user_default']); | ||
58 | static::assertSame('Login - Shaarli', $assignedVariables['pagetitle']); | ||
59 | } | ||
60 | |||
61 | public function testValidControllerInvokeWithUserName(): void | ||
62 | { | ||
63 | $this->createValidContainerMockSet(); | ||
64 | |||
65 | $request = $this->createMock(Request::class); | ||
66 | $request->expects(static::once())->method('getServerParam')->willReturn('> referer'); | ||
67 | $request->expects(static::exactly(2))->method('getParam')->willReturn('myUser>'); | ||
68 | $response = new Response(); | ||
69 | |||
70 | $assignedVariables = []; | ||
71 | $this->container->pageBuilder | ||
72 | ->method('assign') | ||
73 | ->willReturnCallback(function ($key, $value) use (&$assignedVariables) { | ||
74 | $assignedVariables[$key] = $value; | ||
75 | |||
76 | return $this; | ||
77 | }) | ||
78 | ; | ||
79 | |||
80 | $result = $this->controller->index($request, $response); | ||
81 | |||
82 | static::assertInstanceOf(Response::class, $result); | ||
83 | static::assertSame(200, $result->getStatusCode()); | ||
84 | static::assertSame('loginform', (string) $result->getBody()); | ||
85 | |||
86 | static::assertSame('myUser>', $assignedVariables['username']); | ||
87 | static::assertSame('> referer', $assignedVariables['returnurl']); | ||
88 | static::assertSame(true, $assignedVariables['remember_user_default']); | ||
89 | static::assertSame('Login - Shaarli', $assignedVariables['pagetitle']); | ||
90 | } | ||
91 | |||
92 | public function testLoginControllerWhileLoggedIn(): void | ||
93 | { | ||
94 | $request = $this->createMock(Request::class); | ||
95 | $response = new Response(); | ||
96 | |||
97 | $loginManager = $this->createMock(LoginManager::class); | ||
98 | $loginManager->expects(static::once())->method('isLoggedIn')->willReturn(true); | ||
99 | $this->container->loginManager = $loginManager; | ||
100 | |||
101 | $result = $this->controller->index($request, $response); | ||
102 | |||
103 | static::assertInstanceOf(Response::class, $result); | ||
104 | static::assertSame(302, $result->getStatusCode()); | ||
105 | static::assertSame(['./'], $result->getHeader('Location')); | ||
106 | } | ||
107 | |||
108 | public function testLoginControllerOpenShaarli(): void | ||
109 | { | ||
110 | $this->createValidContainerMockSet(); | ||
111 | |||
112 | $request = $this->createMock(Request::class); | ||
113 | $response = new Response(); | ||
114 | |||
115 | $conf = $this->createMock(ConfigManager::class); | ||
116 | $conf->method('get')->willReturnCallback(function (string $parameter, $default) { | ||
117 | if ($parameter === 'security.open_shaarli') { | ||
118 | return true; | ||
119 | } | ||
120 | return $default; | ||
121 | }); | ||
122 | $this->container->conf = $conf; | ||
123 | |||
124 | $result = $this->controller->index($request, $response); | ||
125 | |||
126 | static::assertInstanceOf(Response::class, $result); | ||
127 | static::assertSame(302, $result->getStatusCode()); | ||
128 | static::assertSame(['./'], $result->getHeader('Location')); | ||
129 | } | ||
130 | |||
131 | public function testLoginControllerWhileBanned(): void | ||
132 | { | ||
133 | $this->createValidContainerMockSet(); | ||
134 | |||
135 | $request = $this->createMock(Request::class); | ||
136 | $response = new Response(); | ||
137 | |||
138 | $loginManager = $this->createMock(LoginManager::class); | ||
139 | $loginManager->method('isLoggedIn')->willReturn(false); | ||
140 | $loginManager->method('canLogin')->willReturn(false); | ||
141 | $this->container->loginManager = $loginManager; | ||
142 | |||
143 | $this->expectException(LoginBannedException::class); | ||
144 | |||
145 | $this->controller->index($request, $response); | ||
146 | } | ||
147 | |||
148 | protected function createValidContainerMockSet(): void | ||
149 | { | ||
150 | // User logged out | ||
151 | $loginManager = $this->createMock(LoginManager::class); | ||
152 | $loginManager->method('isLoggedIn')->willReturn(false); | ||
153 | $loginManager->method('canLogin')->willReturn(true); | ||
154 | $this->container->loginManager = $loginManager; | ||
155 | |||
156 | // Config | ||
157 | $conf = $this->createMock(ConfigManager::class); | ||
158 | $conf->method('get')->willReturnCallback(function (string $parameter, $default) { | ||
159 | return $default; | ||
160 | }); | ||
161 | $this->container->conf = $conf; | ||
162 | |||
163 | // PageBuilder | ||
164 | $pageBuilder = $this->createMock(PageBuilder::class); | ||
165 | $pageBuilder | ||
166 | ->method('render') | ||
167 | ->willReturnCallback(function (string $template): string { | ||
168 | return $template; | ||
169 | }) | ||
170 | ; | ||
171 | $this->container->pageBuilder = $pageBuilder; | ||
172 | |||
173 | $pluginManager = $this->createMock(PluginManager::class); | ||
174 | $this->container->pluginManager = $pluginManager; | ||
175 | $bookmarkService = $this->createMock(BookmarkServiceInterface::class); | ||
176 | $this->container->bookmarkService = $bookmarkService; | ||
177 | } | ||
178 | } | ||
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 @@ | |||
1 | <?php | ||
2 | |||
3 | declare(strict_types=1); | ||
4 | |||
5 | namespace Shaarli\Front\Controller; | ||
6 | |||
7 | use PHPUnit\Framework\TestCase; | ||
8 | use Shaarli\Bookmark\BookmarkFilter; | ||
9 | use Shaarli\Bookmark\BookmarkServiceInterface; | ||
10 | use Shaarli\Container\ShaarliContainer; | ||
11 | use Shaarli\Plugin\PluginManager; | ||
12 | use Shaarli\Render\PageBuilder; | ||
13 | use Shaarli\Security\LoginManager; | ||
14 | |||
15 | /** | ||
16 | * Class ShaarliControllerTest | ||
17 | * | ||
18 | * This class is used to test default behavior of ShaarliController abstract class. | ||
19 | * It uses a dummy non abstract controller. | ||
20 | */ | ||
21 | class ShaarliControllerTest extends TestCase | ||
22 | { | ||
23 | /** @var ShaarliContainer */ | ||
24 | protected $container; | ||
25 | |||
26 | /** @var LoginController */ | ||
27 | protected $controller; | ||
28 | |||
29 | /** @var mixed[] List of variable assigned to the template */ | ||
30 | protected $assignedValues; | ||
31 | |||
32 | public function setUp(): void | ||
33 | { | ||
34 | $this->container = $this->createMock(ShaarliContainer::class); | ||
35 | $this->controller = new class($this->container) extends ShaarliController | ||
36 | { | ||
37 | public function assignView(string $key, $value): ShaarliController | ||
38 | { | ||
39 | return parent::assignView($key, $value); | ||
40 | } | ||
41 | |||
42 | public function render(string $template): string | ||
43 | { | ||
44 | return parent::render($template); | ||
45 | } | ||
46 | }; | ||
47 | $this->assignedValues = []; | ||
48 | } | ||
49 | |||
50 | public function testAssignView(): void | ||
51 | { | ||
52 | $this->createValidContainerMockSet(); | ||
53 | |||
54 | $self = $this->controller->assignView('variableName', 'variableValue'); | ||
55 | |||
56 | static::assertInstanceOf(ShaarliController::class, $self); | ||
57 | static::assertSame('variableValue', $this->assignedValues['variableName']); | ||
58 | } | ||
59 | |||
60 | public function testRender(): void | ||
61 | { | ||
62 | $this->createValidContainerMockSet(); | ||
63 | |||
64 | $render = $this->controller->render('templateName'); | ||
65 | |||
66 | static::assertSame('templateName', $render); | ||
67 | |||
68 | static::assertSame(10, $this->assignedValues['linkcount']); | ||
69 | static::assertSame(5, $this->assignedValues['privateLinkcount']); | ||
70 | static::assertSame(['error'], $this->assignedValues['plugin_errors']); | ||
71 | |||
72 | static::assertSame('templateName', $this->assignedValues['plugins_includes']['render_includes']['target']); | ||
73 | static::assertTrue($this->assignedValues['plugins_includes']['render_includes']['loggedin']); | ||
74 | static::assertSame('templateName', $this->assignedValues['plugins_header']['render_header']['target']); | ||
75 | static::assertTrue($this->assignedValues['plugins_header']['render_header']['loggedin']); | ||
76 | static::assertSame('templateName', $this->assignedValues['plugins_footer']['render_footer']['target']); | ||
77 | static::assertTrue($this->assignedValues['plugins_footer']['render_footer']['loggedin']); | ||
78 | } | ||
79 | |||
80 | protected function createValidContainerMockSet(): void | ||
81 | { | ||
82 | $pageBuilder = $this->createMock(PageBuilder::class); | ||
83 | $pageBuilder | ||
84 | ->method('assign') | ||
85 | ->willReturnCallback(function (string $key, $value): void { | ||
86 | $this->assignedValues[$key] = $value; | ||
87 | }); | ||
88 | $pageBuilder | ||
89 | ->method('render') | ||
90 | ->willReturnCallback(function (string $template): string { | ||
91 | return $template; | ||
92 | }); | ||
93 | $this->container->pageBuilder = $pageBuilder; | ||
94 | |||
95 | $bookmarkService = $this->createMock(BookmarkServiceInterface::class); | ||
96 | $bookmarkService | ||
97 | ->method('count') | ||
98 | ->willReturnCallback(function (string $visibility): int { | ||
99 | return $visibility === BookmarkFilter::$PRIVATE ? 5 : 10; | ||
100 | }); | ||
101 | $this->container->bookmarkService = $bookmarkService; | ||
102 | |||
103 | $pluginManager = $this->createMock(PluginManager::class); | ||
104 | $pluginManager | ||
105 | ->method('executeHooks') | ||
106 | ->willReturnCallback(function (string $hook, array &$data, array $params): array { | ||
107 | return $data[$hook] = $params; | ||
108 | }); | ||
109 | $pluginManager->method('getErrors')->willReturn(['error']); | ||
110 | $this->container->pluginManager = $pluginManager; | ||
111 | |||
112 | $loginManager = $this->createMock(LoginManager::class); | ||
113 | $loginManager->method('isLoggedIn')->willReturn(true); | ||
114 | $this->container->loginManager = $loginManager; | ||
115 | } | ||
116 | } | ||
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 @@ | |||
6 | <body> | 6 | <body> |
7 | <div id="pageheader"> | 7 | <div id="pageheader"> |
8 | {include="page.header"} | 8 | {include="page.header"} |
9 | <div class="center" id="page404" class="page404-container"> | 9 | <div id="pageError" class="page-error-container center"> |
10 | <h2>{'Sorry, nothing to see here.'|t}</h2> | 10 | <h2>{'Sorry, nothing to see here.'|t}</h2> |
11 | <img src="img/sad_star.png" alt=""> | 11 | <img src="img/sad_star.png" alt=""> |
12 | <p>{$error_message}</p> | 12 | <p>{$error_message}</p> |
diff --git a/tpl/default/error.html b/tpl/default/error.html new file mode 100644 index 00000000..ef1dfd73 --- /dev/null +++ b/tpl/default/error.html | |||
@@ -0,0 +1,22 @@ | |||
1 | <!DOCTYPE html> | ||
2 | <html{if="$language !== 'auto'"} lang="{$language}"{/if}> | ||
3 | <head> | ||
4 | {include="includes"} | ||
5 | </head> | ||
6 | <body> | ||
7 | <div id="pageheader"> | ||
8 | {include="page.header"} | ||
9 | <div id="pageError" class="page-error-container center"> | ||
10 | <h2>{$message}</h2> | ||
11 | |||
12 | {if="!empty($stacktrace)"} | ||
13 | <pre> | ||
14 | {$stacktrace} | ||
15 | </pre> | ||
16 | {/if} | ||
17 | |||
18 | <img src="img/sad_star.png" alt=""> | ||
19 | </div> | ||
20 | {include="page.footer"} | ||
21 | </body> | ||
22 | </html> | ||
diff --git a/tpl/default/loginform.html b/tpl/default/loginform.html index 761aec0c..90c2b2b6 100644 --- a/tpl/default/loginform.html +++ b/tpl/default/loginform.html | |||
@@ -5,44 +5,32 @@ | |||
5 | </head> | 5 | </head> |
6 | <body> | 6 | <body> |
7 | {include="page.header"} | 7 | {include="page.header"} |
8 | {if="!$user_can_login"} | 8 | <div class="pure-g"> |
9 | <div class="pure-g pure-alert pure-alert-error pure-alert-closable center"> | 9 | <div class="pure-u-lg-1-3 pure-u-1-24"></div> |
10 | <div class="pure-u-2-24"></div> | 10 | <div id="login-form" class="page-form page-form-light pure-u-lg-1-3 pure-u-22-24 login-form-container"> |
11 | <div class="pure-u-20-24"> | 11 | <form method="post" name="loginform"> |
12 | <p>{'You have been banned after too many failed login attempts. Try again later.'|t}</p> | 12 | <h2 class="window-title">{'Login'|t}</h2> |
13 | </div> | 13 | <div> |
14 | <div class="pure-u-2-24"> | 14 | <input type="text" name="login" aria-label="{'Username'|t}" placeholder="{'Username'|t}" |
15 | <i class="fa fa-times pure-alert-close"></i> | 15 | {if="!empty($username)"}value="{$username}"{/if} class="autofocus"> |
16 | </div> | ||
17 | <div> | ||
18 | <input type="password" name="password" aria-label="{'Password'|t}" placeholder="{'Password'|t}" class="autofocus"> | ||
19 | </div> | ||
20 | <div class="remember-me"> | ||
21 | <input type="checkbox" name="longlastingsession" id="longlastingsessionform" | ||
22 | {if="$remember_user_default"}checked="checked"{/if}> | ||
23 | <label for="longlastingsessionform">{'Remember me'|t}</label> | ||
24 | </div> | ||
25 | <div> | ||
26 | <input type="submit" value="{'Login'|t}" class="bigbutton"> | ||
27 | </div> | ||
28 | <input type="hidden" name="token" value="{$token}"> | ||
29 | {if="$returnurl"}<input type="hidden" name="returnurl" value="{$returnurl}">{/if} | ||
30 | </form> | ||
16 | </div> | 31 | </div> |
32 | <div class="pure-u-lg-1-3 pure-u-1-8"></div> | ||
17 | </div> | 33 | </div> |
18 | {else} | ||
19 | <div class="pure-g"> | ||
20 | <div class="pure-u-lg-1-3 pure-u-1-24"></div> | ||
21 | <div id="login-form" class="page-form page-form-light pure-u-lg-1-3 pure-u-22-24 login-form-container"> | ||
22 | <form method="post" name="loginform"> | ||
23 | <h2 class="window-title">{'Login'|t}</h2> | ||
24 | <div> | ||
25 | <input type="text" name="login" aria-label="{'Username'|t}" placeholder="{'Username'|t}" | ||
26 | {if="!empty($username)"}value="{$username}"{/if} class="autofocus"> | ||
27 | </div> | ||
28 | <div> | ||
29 | <input type="password" name="password" aria-label="{'Password'|t}" placeholder="{'Password'|t}" class="autofocus"> | ||
30 | </div> | ||
31 | <div class="remember-me"> | ||
32 | <input type="checkbox" name="longlastingsession" id="longlastingsessionform" | ||
33 | {if="$remember_user_default"}checked="checked"{/if}> | ||
34 | <label for="longlastingsessionform">{'Remember me'|t}</label> | ||
35 | </div> | ||
36 | <div> | ||
37 | <input type="submit" value="{'Login'|t}" class="bigbutton"> | ||
38 | </div> | ||
39 | <input type="hidden" name="token" value="{$token}"> | ||
40 | {if="$returnurl"}<input type="hidden" name="returnurl" value="{$returnurl}">{/if} | ||
41 | </form> | ||
42 | </div> | ||
43 | <div class="pure-u-lg-1-3 pure-u-1-8"></div> | ||
44 | </div> | ||
45 | {/if} | ||
46 | 34 | ||
47 | {include="page.footer"} | 35 | {include="page.footer"} |
48 | </body> | 36 | </body> |
diff --git a/tpl/default/page.header.html b/tpl/default/page.header.html index 4f063dc3..82f8ebf1 100644 --- a/tpl/default/page.header.html +++ b/tpl/default/page.header.html | |||
@@ -60,7 +60,7 @@ | |||
60 | </li> | 60 | </li> |
61 | {else} | 61 | {else} |
62 | <li class="pure-menu-item pure-u-lg-0 shaarli-menu-mobile" id="shaarli-menu-mobile-login"> | 62 | <li class="pure-menu-item pure-u-lg-0 shaarli-menu-mobile" id="shaarli-menu-mobile-login"> |
63 | <a href="?do=login" class="pure-menu-link">{'Login'|t}</a> | 63 | <a href="/login" class="pure-menu-link">{'Login'|t}</a> |
64 | </li> | 64 | </li> |
65 | {/if} | 65 | {/if} |
66 | </ul> | 66 | </ul> |
@@ -80,7 +80,7 @@ | |||
80 | </li> | 80 | </li> |
81 | {if="!$is_logged_in"} | 81 | {if="!$is_logged_in"} |
82 | <li class="pure-menu-item" id="shaarli-menu-desktop-login"> | 82 | <li class="pure-menu-item" id="shaarli-menu-desktop-login"> |
83 | <a href="?do=login" class="pure-menu-link" | 83 | <a href="/login" class="pure-menu-link" |
84 | data-open-id="header-login-form" | 84 | data-open-id="header-login-form" |
85 | id="login-button" aria-label="{'Login'|t}" title="{'Login'|t}"> | 85 | id="login-button" aria-label="{'Login'|t}" title="{'Login'|t}"> |
86 | <i class="fa fa-user" aria-hidden="true"></i> | 86 | <i class="fa fa-user" aria-hidden="true"></i> |
diff --git a/tpl/default/tag.cloud.html b/tpl/default/tag.cloud.html index b9c0b162..7839fcca 100644 --- a/tpl/default/tag.cloud.html +++ b/tpl/default/tag.cloud.html | |||
@@ -32,6 +32,7 @@ | |||
32 | {/if} | 32 | {/if} |
33 | autocomplete="off" data-multiple data-autofirst data-minChars="1" | 33 | autocomplete="off" data-multiple data-autofirst data-minChars="1" |
34 | data-list="{loop="$tags"}{$key}, {/loop}" | 34 | data-list="{loop="$tags"}{$key}, {/loop}" |
35 | class="autofocus" | ||
35 | > | 36 | > |
36 | <button type="submit" class="search-button" aria-label="{'Search'|t}"><i class="fa fa-search" aria-hidden="true"></i></button> | 37 | <button type="submit" class="search-button" aria-label="{'Search'|t}"><i class="fa fa-search" aria-hidden="true"></i></button> |
37 | </form> | 38 | </form> |
diff --git a/tpl/default/thumbnails.html b/tpl/default/thumbnails.html index f1939798..5f9bef08 100644 --- a/tpl/default/thumbnails.html +++ b/tpl/default/thumbnails.html | |||
@@ -38,7 +38,7 @@ | |||
38 | </div> | 38 | </div> |
39 | </div> | 39 | </div> |
40 | 40 | ||
41 | <input type="hidden" name="ids" value="{function="implode($ids, ',')"}" /> | 41 | <input type="hidden" name="ids" value="{function="implode(',', $ids)"}" /> |
42 | </div> | 42 | </div> |
43 | </div> | 43 | </div> |
44 | 44 | ||
diff --git a/tpl/vintage/error.html b/tpl/vintage/error.html new file mode 100644 index 00000000..b6e62be0 --- /dev/null +++ b/tpl/vintage/error.html | |||
@@ -0,0 +1,25 @@ | |||
1 | <!DOCTYPE html> | ||
2 | <html> | ||
3 | <head> | ||
4 | {include="includes"} | ||
5 | </head> | ||
6 | <body> | ||
7 | <div id="pageheader"> | ||
8 | {include="page.header"} | ||
9 | </div> | ||
10 | <div class="error-container"> | ||
11 | <h1>Error</h1> | ||
12 | <p>{$message}</p> | ||
13 | |||
14 | {if="!empty($stacktrace)"} | ||
15 | <br> | ||
16 | <pre> | ||
17 | {$stacktrace} | ||
18 | </pre> | ||
19 | {/if} | ||
20 | |||
21 | <p>Would you mind <a href="?">clicking here</a>?</p> | ||
22 | </div> | ||
23 | {include="page.footer"} | ||
24 | </body> | ||
25 | </html> | ||
diff --git a/tpl/vintage/loginform.html b/tpl/vintage/loginform.html index 0f7d6387..a3792066 100644 --- a/tpl/vintage/loginform.html +++ b/tpl/vintage/loginform.html | |||
@@ -2,36 +2,30 @@ | |||
2 | <html> | 2 | <html> |
3 | <head>{include="includes"}</head> | 3 | <head>{include="includes"}</head> |
4 | <body | 4 | <body |
5 | {if="$user_can_login"} | 5 | {if="empty($username)"} |
6 | {if="empty($username)"} | 6 | onload="document.loginform.login.focus();" |
7 | onload="document.loginform.login.focus();" | 7 | {else} |
8 | {else} | 8 | onload="document.loginform.password.focus();" |
9 | onload="document.loginform.password.focus();" | ||
10 | {/if} | ||
11 | {/if}> | 9 | {/if}> |
12 | <div id="pageheader"> | 10 | <div id="pageheader"> |
13 | {include="page.header"} | 11 | {include="page.header"} |
14 | 12 | ||
15 | <div id="headerform"> | 13 | <div id="headerform"> |
16 | {if="!$user_can_login"} | 14 | <form method="post" name="loginform"> |
17 | You have been banned from login after too many failed attempts. Try later. | 15 | <label for="login">Login: <input type="text" id="login" name="login" tabindex="1" |
18 | {else} | 16 | {if="!empty($username)"}value="{$username}"{/if}> |
19 | <form method="post" name="loginform"> | 17 | </label> |
20 | <label for="login">Login: <input type="text" id="login" name="login" tabindex="1" | 18 | <label for="password">Password: <input type="password" id="password" name="password" tabindex="2"> |
21 | {if="!empty($username)"}value="{$username}"{/if}> | 19 | </label> |
22 | </label> | 20 | <input type="submit" value="Login" class="bigbutton" tabindex="4"> |
23 | <label for="password">Password: <input type="password" id="password" name="password" tabindex="2"> | 21 | <label for="longlastingsession"> |
24 | </label> | 22 | <input type="checkbox" name="longlastingsession" |
25 | <input type="submit" value="Login" class="bigbutton" tabindex="4"> | 23 | id="longlastingsession" tabindex="3" |
26 | <label for="longlastingsession"> | 24 | {if="$remember_user_default"}checked="checked"{/if}> |
27 | <input type="checkbox" name="longlastingsession" | 25 | Stay signed in (Do not check on public computers)</label> |
28 | id="longlastingsession" tabindex="3" | 26 | <input type="hidden" name="token" value="{$token}"> |
29 | {if="$remember_user_default"}checked="checked"{/if}> | 27 | {if="$returnurl"}<input type="hidden" name="returnurl" value="{$returnurl}">{/if} |
30 | Stay signed in (Do not check on public computers)</label> | 28 | </form> |
31 | <input type="hidden" name="token" value="{$token}"> | ||
32 | {if="$returnurl"}<input type="hidden" name="returnurl" value="{$returnurl}">{/if} | ||
33 | </form> | ||
34 | {/if} | ||
35 | </div> | 29 | </div> |
36 | </div> | 30 | </div> |
37 | 31 | ||
diff --git a/tpl/vintage/page.header.html b/tpl/vintage/page.header.html index 40c53e5b..a37926d2 100644 --- a/tpl/vintage/page.header.html +++ b/tpl/vintage/page.header.html | |||
@@ -25,7 +25,7 @@ | |||
25 | <li><a href="?do=tools">Tools</a></li> | 25 | <li><a href="?do=tools">Tools</a></li> |
26 | <li><a href="?do=addlink">Add link</a></li> | 26 | <li><a href="?do=addlink">Add link</a></li> |
27 | {else} | 27 | {else} |
28 | <li><a href="?do=login">Login</a></li> | 28 | <li><a href="/login">Login</a></li> |
29 | {/if} | 29 | {/if} |
30 | <li><a href="{$feedurl}?do=rss{$searchcrits}" class="nomobile">RSS Feed</a></li> | 30 | <li><a href="{$feedurl}?do=rss{$searchcrits}" class="nomobile">RSS Feed</a></li> |
31 | {if="$showatom"} | 31 | {if="$showatom"} |
diff --git a/tpl/vintage/thumbnails.html b/tpl/vintage/thumbnails.html index 79aebf8d..5cad845b 100644 --- a/tpl/vintage/thumbnails.html +++ b/tpl/vintage/thumbnails.html | |||
@@ -20,7 +20,7 @@ | |||
20 | </div> | 20 | </div> |
21 | </div> | 21 | </div> |
22 | 22 | ||
23 | <input type="hidden" name="ids" value="{function="implode($ids, ',')"}" /> | 23 | <input type="hidden" name="ids" value="{function="implode(',', $ids)"}" /> |
24 | 24 | ||
25 | {include="page.footer"} | 25 | {include="page.footer"} |
26 | <script src="js/thumbnails_update.min.js?v={$version_hash}"></script> | 26 | <script src="js/thumbnails_update.min.js?v={$version_hash}"></script> |