diff --git a/.github/Dependabot.yml b/.github/Dependabot.yml new file mode 100644 index 0000000..3840137 --- /dev/null +++ b/.github/Dependabot.yml @@ -0,0 +1,36 @@ +# Dependabot configuration for AsBuiltReport.Core +# https://docs.github.com/en/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file + +version: 2 +updates: + # Monitor GitHub Actions + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "weekly" + day: "monday" + labels: + - "dependencies" + - "github-actions" + commit-message: + prefix: "ci" + include: "scope" + open-pull-requests-limit: 5 + + # Monitor PowerShell modules (via manifest) + - package-ecosystem: "nuget" + directory: "/" + schedule: + interval: "weekly" + day: "monday" + labels: + - "dependencies" + - "powershell" + commit-message: + prefix: "deps" + include: "scope" + open-pull-requests-limit: 5 + ignore: + # PScribo updates should be reviewed manually + - dependency-name: "PScribo" + update-types: ["version-update:semver-major"] diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 0000000..38a40cf --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1,15 @@ +# These are supported funding model platforms + +#github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] +#patreon: # Replace with a single Patreon username +#open_collective: # Replace with a single Open Collective username +ko_fi: B0B7DDGZ7 +#tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel +#community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry +#liberapay: # Replace with a single Liberapay username +#issuehunt: # Replace with a single IssueHunt username +#lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry +#polar: # Replace with a single Polar username +#buy_me_a_coffee: # Replace with a single Buy Me a Coffee username +#thanks_dev: # Replace with a single thanks.dev username +#custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 74a3faa..5ddca93 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -31,4 +31,4 @@ - [ ] My code follows the code style of this project. - [ ] My change requires a change to the documentation. - [ ] I have updated the documentation accordingly. -- [ ] I have read the [**CONTRIBUTING**](https://www.asbuiltreport.com/about/contributing/) page. +- [ ] I have read the [**CONTRIBUTING**](/CONTRIBUTING.md) page. diff --git a/.github/workflows/PSScriptAnalyzer.yml b/.github/workflows/PSScriptAnalyzer.yml index 57b2ea4..eea40a8 100644 --- a/.github/workflows/PSScriptAnalyzer.yml +++ b/.github/workflows/PSScriptAnalyzer.yml @@ -3,6 +3,9 @@ on: [push, pull_request] jobs: lint: name: Run PSScriptAnalyzer + permissions: + contents: read + pull-requests: write runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 diff --git a/.github/workflows/Pester.yml b/.github/workflows/Pester.yml new file mode 100644 index 0000000..c14b719 --- /dev/null +++ b/.github/workflows/Pester.yml @@ -0,0 +1,84 @@ +name: Pester Tests + +permissions: + contents: read + +on: + push: + branches: [main, dev, master] + pull_request: + branches: [main, dev, master] + workflow_dispatch: + +jobs: + test: + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: [windows-latest, ubuntu-latest, macos-latest] + psversion: [pwsh, powershell] + exclude: + # PowerShell 5.1 (powershell) is only available on Windows + - os: ubuntu-latest + psversion: powershell + - os: macos-latest + psversion: powershell + + name: Test on ${{ matrix.os }} with ${{ matrix.psversion == 'pwsh' && 'PowerShell 7.x' || 'PowerShell 5.1' }} + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Install required modules (PowerShell 7.x) + if: matrix.psversion == 'pwsh' + shell: pwsh + run: | + Set-PSRepository -Name PSGallery -InstallationPolicy Trusted + Install-Module -Name Pester -MinimumVersion 5.0.0 -Force -SkipPublisherCheck + Install-Module -Name PScribo -MinimumVersion 0.11.1 -Force + + - name: Install required modules (PowerShell 5.1) + if: matrix.psversion == 'powershell' + shell: powershell + run: | + Set-PSRepository -Name PSGallery -InstallationPolicy Trusted + Install-Module -Name Pester -MinimumVersion 5.0.0 -Force -SkipPublisherCheck + Install-Module -Name PScribo -MinimumVersion 0.11.1 -Force + + - name: Run Pester tests (PowerShell 7.x) + if: matrix.psversion == 'pwsh' + shell: pwsh + run: | + .\Tests\Invoke-Tests.ps1 -CodeCoverage -OutputFormat NUnitXml + + - name: Run Pester tests (PowerShell 5.1) + if: matrix.psversion == 'powershell' + shell: powershell + run: | + .\Tests\Invoke-Tests.ps1 -CodeCoverage -OutputFormat NUnitXml + + - name: Upload test results + if: always() + uses: actions/upload-artifact@v4 + with: + name: test-results-${{ matrix.os }}-${{ matrix.psversion }} + path: testResults.xml + + - name: Upload code coverage + if: always() && matrix.os == 'windows-latest' && matrix.psversion == 'pwsh' + uses: actions/upload-artifact@v4 + with: + name: code-coverage + path: coverage.xml + + - name: Upload coverage reports to Codecov + if: always() && matrix.os == 'windows-latest' && matrix.psversion == 'pwsh' + uses: codecov/codecov-action@v5 + with: + token: ${{ secrets.CODECOV_TOKEN }} + slug: AsBuiltReport/AsBuiltReport.Core + files: ./coverage.xml + flags: unittests + fail_ci_if_error: false diff --git a/.github/workflows/Release.yml b/.github/workflows/Release.yml index a197fb0..5bd70af 100644 --- a/.github/workflows/Release.yml +++ b/.github/workflows/Release.yml @@ -1,5 +1,6 @@ name: Publish PowerShell Module - +permissions: + contents: read on: release: types: [published] @@ -20,11 +21,11 @@ jobs: - name: Test Module Manifest shell: pwsh run: | - Test-ModuleManifest .\AsBuiltReport.Core.psd1 + Test-ModuleManifest .\AsBuiltReport.Core\AsBuiltReport.Core.psd1 - name: Publish module to PowerShell Gallery shell: pwsh run: | - Publish-Module -Path ./ -NuGetApiKey ${{ secrets.PSGALLERY_API_KEY }} -Verbose + Publish-Module -Path .\AsBuiltReport.Core\ -NuGetApiKey ${{ secrets.PSGALLERY_API_KEY }} -Verbose tweet: needs: publish-to-gallery runs-on: ubuntu-latest diff --git a/.github/workflows/Stale.yml b/.github/workflows/Stale.yml new file mode 100644 index 0000000..ac3ee8d --- /dev/null +++ b/.github/workflows/Stale.yml @@ -0,0 +1,21 @@ +name: 'Close stale issues and PRs' +on: + schedule: + - cron: '30 1 * * *' + +jobs: + stale: + permissions: + issues: write + pull-requests: write + runs-on: ubuntu-latest + steps: + - uses: actions/stale@v9 + with: + stale-issue-message: 'This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.' + days-before-stale: 60 + days-before-close: 7 + exempt-pr-labels: 'help wanted,enhancement,security,pinned' + stale-pr-label: 'wontfix' + stale-issue-label: 'wontfix' + exempt-issue-labels: 'help wanted,enhancement,security,pinned' diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a8b0903 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +.claude/ +.vscode/launch.json +coverage.xml \ No newline at end of file diff --git a/AsBuiltReport.Core.Style.ps1 b/AsBuiltReport.Core.Style.ps1 deleted file mode 100644 index 133751d..0000000 --- a/AsBuiltReport.Core.Style.ps1 +++ /dev/null @@ -1,112 +0,0 @@ -# AsBuiltReport Default Document Style - -# Configure document options -DocumentOption -EnableSectionNumbering -PageSize A4 -DefaultFont 'Segoe Ui' -MarginLeftAndRight 71 -MarginTopAndBottom 71 -Orientation $Orientation - -# Configure Title & Heading Styles -Style -Name 'Title' -Size 24 -Color '072E58' -Align Center -Style -Name 'Title 2' -Size 18 -Color '204369' -Align Center -Style -Name 'Title 3' -Size 12 -Color '395879' -Align Left -Style -Name 'Heading 1' -Size 16 -Color '072E58' -Style -Name 'Heading 2' -Size 14 -Color '204369' -Style -Name 'Heading 3' -Size 13 -Color '395879' -Style -Name 'Heading 4' -Size 12 -Color '958026' -Style -Name 'NO TOC Heading 4' -Size 12 -Color '958026' -Style -Name 'Heading 5' -Size 11 -Color '009684' -Style -Name 'NO TOC Heading 5' -Size 11 -Color '009684' -Style -Name 'Heading 6' -Size 10 -Color '009683' -Style -Name 'NO TOC Heading 6' -Size 10 -Color '009683' -Style -Name 'NO TOC Heading 7' -Size 10 -Color '00EBCD' -Italic -Style -Name 'Normal' -Size 10 -Color '565656' -Default -# Header & Footer Styles -Style -Name 'Header' -Size 10 -Color '565656' -Align Center -Style -Name 'Footer' -Size 10 -Color '565656' -Align Center -# Table of Contents Style -Style -Name 'TOC' -Size 16 -Color '072E58' -# Table Heading & Row Styles -Style -Name 'TableDefaultHeading' -Size 10 -Color 'FAFAFA' -BackgroundColor '072E58' -Style -Name 'TableDefaultRow' -Size 10 -Color '565656' -# Table Row/Cell Highlight Styles -Style -Name 'Critical' -Size 10 -Color '565656' -BackgroundColor 'FEDDD7' -Style -Name 'Warning' -Size 10 -Color '565656' -BackgroundColor 'FFF4C7' -Style -Name 'Info' -Size 10 -Color '565656' -BackgroundColor 'E3F5FC' -Style -Name 'OK' -Size 10 -Color '565656' -BackgroundColor 'DFF0D0' -# Table Caption Style -Style -Name 'Caption' -Size 10 -Color '072E58' -Italic -Align Left - -# Configure Table Styles -$TableDefaultProperties = @{ - Id = 'TableDefault' - HeaderStyle = 'TableDefaultHeading' - RowStyle = 'TableDefaultRow' - BorderColor = '072E58' - Align = 'Left' - CaptionStyle = 'Caption' - CaptionLocation = 'Below' - BorderWidth = 0.25 - PaddingTop = 1 - PaddingBottom = 1.5 - PaddingLeft = 2 - PaddingRight = 2 -} - -TableStyle @TableDefaultProperties -Default -TableStyle -Id 'Borderless' -HeaderStyle Normal -RowStyle Normal -BorderWidth 0 - -# Cover Page Layout -# Set Header & Footer, if enabled in report JSON configuration -if ($ReportConfig.Report.ShowHeaderFooter) { - Header -Default { - Paragraph -Style Header "$($ReportConfig.Report.Name) - v$($ReportConfig.Report.Version)" - } - - Footer -Default { - Paragraph -Style Footer 'Page ' - } -} - -# Set position of cover page image, report titles and other information based on page orientatio -if (-not ($ReportConfig.Report.ShowCoverPageImage)) { - $LineCount = 7 -} -if ($Orientation -eq 'Portrait') { - BlankLine -Count 11 - $LineCount = 22 + $LineCount -} else { - BlankLine -Count 7 - $LineCount = 9 + $LineCount -} - -# Show cover page image, if enabled in report JSON configuration -if ($ReportConfig.Report.ShowCoverPageImage) { - Try { - Image -Text 'AsBuiltReport Logo' -Align 'Center' -Percent 45 -Base64 "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" - BlankLine -Count 1 - } Catch { - Write-PScriboMessage -IsWarning "Unable to display cover page image. Please set 'ShowCoverPageImage' to 'false' in the report JSON configuration file to avoid this error." - } -} - -# Add Report Name -Paragraph -Style Title $ReportConfig.Report.Name - -if ($AsBuiltConfig.Company.FullName) { - # Add Company Name if specified - BlankLine -Count 1 - Paragraph -Style Title2 $AsBuiltConfig.Company.FullName - BlankLine -Count $LineCount -} else { - BlankLine -Count ($LineCount + 1) -} -Table -Name 'Cover Page' -List -Style Borderless -Width 0 -Hashtable ([Ordered] @{ - 'Author:' = $AsBuiltConfig.Report.Author - 'Date:' = (Get-Date).ToLongDateString() - 'Version:' = $ReportConfig.Report.Version - }) -PageBreak - -if ($ReportConfig.Report.ShowTableOfContents) { - # Add Table of Contents - TOC -Name 'Table of Contents' - PageBreak -} diff --git a/AsBuiltReport.Core.psm1 b/AsBuiltReport.Core.psm1 deleted file mode 100644 index 45ae8e6..0000000 --- a/AsBuiltReport.Core.psm1 +++ /dev/null @@ -1,12 +0,0 @@ -# Get public function definition files and dot source them -$Public = @(Get-ChildItem -Path $PSScriptRoot\Src\Public\*.ps1) - -foreach ($Module in ($Public)) { - try { - . $Module.FullName - } catch { - Write-Error -Message "Failed to import function $($Module.FullName): $_" - } -} - -Export-ModuleMember -Function $Public.BaseName diff --git a/AsBuiltReport.Core/AsBuiltReport.Core.Style.ps1 b/AsBuiltReport.Core/AsBuiltReport.Core.Style.ps1 new file mode 100644 index 0000000..f5501e6 --- /dev/null +++ b/AsBuiltReport.Core/AsBuiltReport.Core.Style.ps1 @@ -0,0 +1,134 @@ +# AsBuiltReport Default Document Style +try { + # Try to initialize localized data for style elements + # Use the report language from parent scope if available, otherwise fallback to OS language + if ($PSScriptRoot) { + if ($FinalReportLanguage) { + Initialize-LocalizedData -ModuleBasePath $PSScriptRoot -LanguageFile 'AsBuiltReportCoreStyle' -ModuleType 'Core' -Language $FinalReportLanguage + } else { + Initialize-LocalizedData -ModuleBasePath $PSScriptRoot -LanguageFile 'AsBuiltReportCoreStyle' -ModuleType 'Core' + } + } else { + # Fallback if $PSScriptRoot is not available + $StyleModulePath = Split-Path -Path $MyInvocation.MyCommand.Path -Parent + if ($FinalReportLanguage) { + Initialize-LocalizedData -ModuleBasePath $StyleModulePath -LanguageFile 'AsBuiltReportCoreStyle' -ModuleType 'Core' -Language $FinalReportLanguage + } else { + Initialize-LocalizedData -ModuleBasePath $StyleModulePath -LanguageFile 'AsBuiltReportCoreStyle' -ModuleType 'Core' + } + } +} catch { + # If localization fails, continue with default style (don't break report generation) + Write-Warning "Could not load style localization: $($_.Exception.Message)" +} + +# Configure document options +DocumentOption -EnableSectionNumbering -PageSize A4 -DefaultFont 'Segoe Ui' -MarginLeftAndRight 71 -MarginTopAndBottom 71 -Orientation $Orientation + +# Configure Title & Heading Styles +Style -Name 'Title' -Size 24 -Color '072E58' -Align Center +Style -Name 'Title 2' -Size 18 -Color '204369' -Align Center +Style -Name 'Title 3' -Size 12 -Color '395879' -Align Left +Style -Name 'Heading 1' -Size 16 -Color '072E58' +Style -Name 'Heading 2' -Size 14 -Color '204369' +Style -Name 'Heading 3' -Size 13 -Color '395879' +Style -Name 'Heading 4' -Size 12 -Color '958026' +Style -Name 'NO TOC Heading 4' -Size 12 -Color '958026' +Style -Name 'Heading 5' -Size 11 -Color '009684' +Style -Name 'NO TOC Heading 5' -Size 11 -Color '009684' +Style -Name 'Heading 6' -Size 10 -Color '009683' +Style -Name 'NO TOC Heading 6' -Size 10 -Color '009683' +Style -Name 'NO TOC Heading 7' -Size 10 -Color '00EBCD' -Italic +Style -Name 'Normal' -Size 10 -Color '565656' -Default +# Header & Footer Styles +Style -Name 'Header' -Size 10 -Color '565656' -Align Center +Style -Name 'Footer' -Size 10 -Color '565656' -Align Center +# Table of Contents Style +Style -Name 'TOC' -Size 16 -Color '072E58' +# Table Heading & Row Styles +Style -Name 'TableDefaultHeading' -Size 10 -Color 'FAFAFA' -BackgroundColor '072E58' +Style -Name 'TableDefaultRow' -Size 10 -Color '565656' +# Table Row/Cell Highlight Styles +Style -Name 'Critical' -Size 10 -Color '565656' -BackgroundColor 'FEDDD7' +Style -Name 'Warning' -Size 10 -Color '565656' -BackgroundColor 'FFF4C7' +Style -Name 'Info' -Size 10 -Color '565656' -BackgroundColor 'E3F5FC' +Style -Name 'OK' -Size 10 -Color '565656' -BackgroundColor 'DFF0D0' +# Table Caption Style +Style -Name 'Caption' -Size 10 -Color '072E58' -Italic -Align Left + +# Configure Table Styles +$TableDefaultProperties = @{ + Id = 'TableDefault' + HeaderStyle = 'TableDefaultHeading' + RowStyle = 'TableDefaultRow' + BorderColor = '072E58' + Align = 'Left' + CaptionStyle = 'Caption' + CaptionLocation = 'Below' + BorderWidth = 0.25 + PaddingTop = 1 + PaddingBottom = 1.5 + PaddingLeft = 2 + PaddingRight = 2 +} + +TableStyle @TableDefaultProperties -Default +TableStyle -Id 'Borderless' -HeaderStyle Normal -RowStyle Normal -BorderWidth 0 + +# Cover Page Layout +# Set Header & Footer, if enabled in report JSON configuration +if ($ReportConfig.Report.ShowHeaderFooter) { + Header -Default { + Paragraph -Style Header "$($ReportConfig.Report.Name) - v$($ReportConfig.Report.Version)" + } + + Footer -Default { + Paragraph -Style Footer $translate.Footer + } +} + +# Set position of cover page image, report titles and other information based on page orientatio +if (-not ($ReportConfig.Report.ShowCoverPageImage)) { + $LineCount = 7 +} +if ($Orientation -eq 'Portrait') { + BlankLine -Count 11 + $LineCount = 22 + $LineCount +} else { + BlankLine -Count 7 + $LineCount = 9 + $LineCount +} + +# Show cover page image, if enabled in report JSON configuration +if ($ReportConfig.Report.ShowCoverPageImage) { + try { + Image -Text $translate.Logo -Align 'Center' -Percent 45 -Base64 "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" + BlankLine -Count 1 + } catch { + Write-PScriboMessage -IsWarning $translate.CoverPageWarning + } +} + +# Add Report Name +Paragraph -Style Title $ReportConfig.Report.Name + +if ($AsBuiltConfig.Company.FullName) { + # Add Company Name if specified + BlankLine -Count 1 + Paragraph -Style Title2 $AsBuiltConfig.Company.FullName + BlankLine -Count $LineCount +} else { + BlankLine -Count ($LineCount + 1) +} +Table -Name $translate.CoverPage -List -Style Borderless -Width 0 -Hashtable ([Ordered] @{ + $translate.Author = $AsBuiltConfig.Report.Author + $translate.Date = (Get-Date).ToLongDateString() + $translate.Version = $ReportConfig.Report.Version + }) +PageBreak + +if ($ReportConfig.Report.ShowTableOfContents) { + # Add Table of Contents + TOC -Name $translate.TOC + PageBreak +} diff --git a/AsBuiltReport.Core.psd1 b/AsBuiltReport.Core/AsBuiltReport.Core.psd1 similarity index 93% rename from AsBuiltReport.Core.psd1 rename to AsBuiltReport.Core/AsBuiltReport.Core.psd1 index 672d822..83c82d8 100644 --- a/AsBuiltReport.Core.psd1 +++ b/AsBuiltReport.Core/AsBuiltReport.Core.psd1 @@ -1,138 +1,138 @@ -# -# Module manifest for module 'AsBuiltReport.core' -# -# Generated by: Tim Carman -# -# Generated on: 7/04/2019 -# - -@{ - - # Script module or binary module file associated with this manifest. - RootModule = 'AsBuiltReport.Core.psm1' - - # Version number of this module. - - ModuleVersion = '1.4.3' - - # Supported PSEditions - # CompatiblePSEditions = 'Desktop' - - # ID used to uniquely identify this module - GUID = '0f1094c4-c6b1-495c-8cdd-9331f67f9f6f' - - # Author of this module - Author = 'Tim Carman' - - # Company or vendor of this module - # CompanyName = '' - - # Copyright statement for this module - Copyright = '(c) 2025 Tim Carman. All rights reserved.' - - # Description of the functionality provided by this module - Description = 'A PowerShell module which provides the core framework for generating As-Built documentation for many common datacentre systems.' - - # Minimum version of the Windows PowerShell engine required by this module - # PowerShellVersion = '5.1' - - # Name of the Windows PowerShell host required by this module - # PowerShellHostName = '' - - # Minimum version of the Windows PowerShell host required by this module - # PowerShellHostVersion = '' - - # Minimum version of Microsoft .NET Framework required by this module. This prerequisite is valid for the PowerShell Desktop edition only. - # DotNetFrameworkVersion = '' - - # Minimum version of the common language runtime (CLR) required by this module. This prerequisite is valid for the PowerShell Desktop edition only. - # CLRVersion = '' - - # Processor architecture (None, X86, Amd64) required by this module - # ProcessorArchitecture = '' - - # Modules that must be imported into the global environment prior to importing this module - RequiredModules = @( - @{ - ModuleName = 'PScribo'; - ModuleVersion = '0.11.1' - } - ) - - # Assemblies that must be loaded prior to importing this module - # RequiredAssemblies = @() - - # Script files (.ps1) that are run in the caller's environment prior to importing this module. - # ScriptsToProcess = @() - - # Type files (.ps1xml) to be loaded when importing this module - # TypesToProcess = @() - - # Format files (.ps1xml) to be loaded when importing this module - # FormatsToProcess = @() - - # Modules to import as nested modules of the module specified in RootModule/ModuleToProcess - # NestedModules = @() - - # Functions to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no functions to export. - FunctionsToExport = 'New-AsBuiltReport', 'New-AsBuiltConfig', 'New-AsBuiltReportConfig' - - # Cmdlets to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no cmdlets to export. - # CmdletsToExport = @() - - # Variables to export from this module - # VariablesToExport = @() - - # Aliases to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no aliases to export. - # AliasesToExport = @() - - # DSC resources to export from this module - # DscResourcesToExport = @() - - # List of all modules packaged with this module - # ModuleList = @() - - # List of all files packaged with this module - # FileList = @() - - # Private data to pass to the module specified in RootModule/ModuleToProcess. This may also contain a PSData hashtable with additional module metadata used by PowerShell. - PrivateData = @{ - - PSData = @{ - - # Tags applied to this module. These help with module discovery in online galleries. - Tags = 'AsBuiltReport', 'Report', 'Documentation', 'PScribo', 'Windows', 'Linux', 'MacOS', 'PSEdition_Desktop', 'PSEdition_Core' - - # A URL to the license for this module. - LicenseUri = 'https://raw.githubusercontent.com/AsBuiltReport/AsBuiltReport.Core/master/LICENSE' - - # A URL to the main website for this project. - ProjectUri = 'https://github.com/AsBuiltReport/AsBuiltReport.Core' - - # A URL to an icon representing this module. - IconUri = 'https://github.com/AsBuiltReport.png' - - # ReleaseNotes of this module - ReleaseNotes = 'https://raw.githubusercontent.com/AsBuiltReport/AsBuiltReport.Core/master/CHANGELOG.md' - - # Prerelease string of this module - # Prerelease = '' - - # Flag to indicate whether the module requires explicit user acceptance for install/update/save - # RequireLicenseAcceptance = $false - - # External dependent modules of this module - # ExternalModuleDependencies = @() - - } # End of PSData hashtable - - } # End of PrivateData hashtable - - # HelpInfo URI of this module - # HelpInfoURI = '' - - # Default prefix for commands exported from this module. Override the default prefix using Import-Module -Prefix. - # DefaultCommandPrefix = '' - -} - +# +# Module manifest for module 'AsBuiltReport.core' +# +# Generated by: Tim Carman +# +# Generated on: 7/04/2019 +# + +@{ + + # Script module or binary module file associated with this manifest. + RootModule = 'AsBuiltReport.Core.psm1' + + # Version number of this module. + + ModuleVersion = '1.5.0' + + # Supported PSEditions + CompatiblePSEditions = @('Desktop', 'Core') + + # ID used to uniquely identify this module + GUID = '0f1094c4-c6b1-495c-8cdd-9331f67f9f6f' + + # Author of this module + Author = 'Tim Carman' + + # Company or vendor of this module + # CompanyName = '' + + # Copyright statement for this module + Copyright = '(c) 2025 Tim Carman. All rights reserved.' + + # Description of the functionality provided by this module + Description = 'A PowerShell module which provides the core framework for generating As-Built documentation for many common datacentre systems.' + + # Minimum version of the Windows PowerShell engine required by this module + PowerShellVersion = '5.1' + + # Name of the Windows PowerShell host required by this module + # PowerShellHostName = '' + + # Minimum version of the Windows PowerShell host required by this module + # PowerShellHostVersion = '' + + # Minimum version of Microsoft .NET Framework required by this module. This prerequisite is valid for the PowerShell Desktop edition only. + # DotNetFrameworkVersion = '' + + # Minimum version of the common language runtime (CLR) required by this module. This prerequisite is valid for the PowerShell Desktop edition only. + # CLRVersion = '' + + # Processor architecture (None, X86, Amd64) required by this module + # ProcessorArchitecture = '' + + # Modules that must be imported into the global environment prior to importing this module + RequiredModules = @( + @{ + ModuleName = 'PScribo'; + ModuleVersion = '0.11.1' + } + ) + + # Assemblies that must be loaded prior to importing this module + # RequiredAssemblies = @() + + # Script files (.ps1) that are run in the caller's environment prior to importing this module. + # ScriptsToProcess = @() + + # Type files (.ps1xml) to be loaded when importing this module + # TypesToProcess = @() + + # Format files (.ps1xml) to be loaded when importing this module + # FormatsToProcess = @() + + # Modules to import as nested modules of the module specified in RootModule/ModuleToProcess + # NestedModules = @() + + # Functions to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no functions to export. + FunctionsToExport = 'New-AsBuiltReport', 'New-AsBuiltConfig', 'New-AsBuiltReportConfig' + + # Cmdlets to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no cmdlets to export. + # CmdletsToExport = @() + + # Variables to export from this module + # VariablesToExport = @() + + # Aliases to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no aliases to export. + # AliasesToExport = @() + + # DSC resources to export from this module + # DscResourcesToExport = @() + + # List of all modules packaged with this module + # ModuleList = @() + + # List of all files packaged with this module + # FileList = @() + + # Private data to pass to the module specified in RootModule/ModuleToProcess. This may also contain a PSData hashtable with additional module metadata used by PowerShell. + PrivateData = @{ + + PSData = @{ + + # Tags applied to this module. These help with module discovery in online galleries. + Tags = 'AsBuiltReport', 'Report', 'Documentation', 'PScribo', 'Windows', 'Linux', 'MacOS', 'PSEdition_Desktop', 'PSEdition_Core' + + # A URL to the license for this module. + LicenseUri = 'https://raw.githubusercontent.com/AsBuiltReport/AsBuiltReport.Core/master/LICENSE' + + # A URL to the main website for this project. + ProjectUri = 'https://github.com/AsBuiltReport/AsBuiltReport.Core' + + # A URL to an icon representing this module. + IconUri = 'https://raw.githubusercontent.com/AsBuiltReport/.github/main/profile/images/AsBuiltReport.png' + + # ReleaseNotes of this module + ReleaseNotes = 'https://raw.githubusercontent.com/AsBuiltReport/AsBuiltReport.Core/master/CHANGELOG.md' + + # Prerelease string of this module + # Prerelease = '' + + # Flag to indicate whether the module requires explicit user acceptance for install/update/save + # RequireLicenseAcceptance = $false + + # External dependent modules of this module + ExternalModuleDependencies = @('PScribo') + + } # End of PSData hashtable + + } # End of PrivateData hashtable + + # HelpInfo URI of this module + # HelpInfoURI = '' + + # Default prefix for commands exported from this module. Override the default prefix using Import-Module -Prefix. + # DefaultCommandPrefix = '' + +} + diff --git a/AsBuiltReport.Core/AsBuiltReport.Core.psm1 b/AsBuiltReport.Core/AsBuiltReport.Core.psm1 new file mode 100644 index 0000000..73660b3 --- /dev/null +++ b/AsBuiltReport.Core/AsBuiltReport.Core.psm1 @@ -0,0 +1,23 @@ +# Get public and private function definition files and dot source them +$Public = @(Get-ChildItem -Path $PSScriptRoot\Src\Public\*.ps1 -ErrorAction SilentlyContinue) +$Private = @(Get-ChildItem -Path $PSScriptRoot\Src\Private\*.ps1 -ErrorAction SilentlyContinue) + +foreach ($Module in @($Public + $Private)) { + try { + . $Module.FullName + } catch { + Write-Error -Message "Failed to import function $($Module.FullName): $_" + } +} + +# Export public functions +Export-ModuleMember -Function $Public.BaseName + +# Make helper functions available globally for report modules to use +# This keeps them out of the public API but accessible from report modules +$GlobalFunctions = @('Write-ReportModuleInfo', 'Get-RequiredModule') +foreach ($FunctionName in $GlobalFunctions) { + if (Get-Command -Name $FunctionName -ErrorAction SilentlyContinue) { + Set-Item -Path "Function:\Global:$FunctionName" -Value (Get-Command $FunctionName).ScriptBlock + } +} diff --git a/AsBuiltReport.Core/Language/ar-SA/AsBuiltReportCoreStyle.psd1 b/AsBuiltReport.Core/Language/ar-SA/AsBuiltReportCoreStyle.psd1 new file mode 100644 index 0000000..69baa90 --- /dev/null +++ b/AsBuiltReport.Core/Language/ar-SA/AsBuiltReportCoreStyle.psd1 @@ -0,0 +1,11 @@ +# culture = 'ar-SA' +ConvertFrom-StringData @' + Footer = صفحة + Logo = شعار AsBuiltReport + CoverPageWarning = تعذر عرض صورة صفحة الغلاف. يرجى تعيين 'ShowCoverPageImage' إلى 'false' في ملف تكوين JSON للتقرير لتجنب هذا الخطأ. + CoverPage = صفحة الغلاف + Author = المؤلف: + Date = التاريخ: + Version = الإصدار: + TOC = جدول المحتويات +'@ diff --git a/AsBuiltReport.Core/Language/ar-SA/New-AsBuiltConfig.psd1 b/AsBuiltReport.Core/Language/ar-SA/New-AsBuiltConfig.psd1 new file mode 100644 index 0000000..8ae6b0a --- /dev/null +++ b/AsBuiltReport.Core/Language/ar-SA/New-AsBuiltConfig.psd1 @@ -0,0 +1,58 @@ +# culture = 'ar-SA' +@{ + +# As Built Report Information +ReportInfo = ConvertFrom-StringData @' + BannerTitle = معلومات As Built Report + ReportAuthor = أدخل اسم المؤلف لهذا As Built Report [{0}] +'@ + +# Company Configuration +CompanyConfig = ConvertFrom-StringData @' + BannerTitle = معلومات الشركة + CompanyInfo = هل ترغب في إدخال معلومات الشركة لـ As Built Report؟ (y/N) + CompanyFullName = أدخل الاسم الكامل للشركة + CompanyShortName = أدخل الاسم المختصر للشركة + CompanyContact = أدخل جهة اتصال الشركة + CompanyEmail = أدخل عنوان البريد الإلكتروني للشركة + CompanyPhone = أدخل رقم هاتف الشركة + CompanyAddress = أدخل عنوان الشركة +'@ + +# Email Configuration +EmailConfig = ConvertFrom-StringData @' + BannerTitle = إعدادات البريد الإلكتروني + ConfigureMailSettings = هل ترغب في إدخال إعدادات SMTP؟ (y/N) + MailServer = أدخل FQDN / عنوان IP لخادم البريد + EmptyMailServerAddress = لا يمكن أن يكون عنوان خادم البريد فارغًا. يرجى إدخال FQDN / عنوان IP صالح لخادم البريد. + InvalidMailServer = '{0}' ليس FQDN أو عنوان IP صالحًا. يرجى إدخال FQDN / عنوان IP صالح لخادم البريد. + MailServerPort587 = أدخل رقم منفذ خادم البريد [587] + InvalidMailServerPort587 = رقم منفذ غير صالح. يرجى إدخال رقم بين 1 و 65535، أو اضغط على Enter للقيمة الافتراضية [587]. + MailServerPort25 = أدخل رقم منفذ خادم البريد [25] + InvalidMailServerPort25 = رقم منفذ غير صالح. يرجى إدخال رقم بين 1 و 65535، أو اضغط على Enter للقيمة الافتراضية [25]. + MailServerUseSSL = استخدام SSL لاتصال خادم البريد؟ (y/N) + MailCredentials = هل يتطلب خادم البريد المصادقة؟ (y/N) + MailFrom = أدخل عنوان البريد الإلكتروني للمرسل + MailTo = أدخل عنوان البريد الإلكتروني للمستلم + EmptyEmail = لا يمكن أن يكون عنوان البريد الإلكتروني فارغًا. يرجى إدخال عنوان بريد إلكتروني صالح. + InvalidEmail = '{0}' ليس عنوان بريد إلكتروني صالحًا. يرجى إدخال عنوان بريد إلكتروني صالح. + AnotherRecipient = هل تريد إدخال مستلم آخر؟ (y/N) + MailBodyPrompt = أدخل محتوى نص رسالة البريد الإلكتروني + MailBody = As Built Report مرفق +'@ + +# Report Configuration +ReportConfig = ConvertFrom-StringData @' + BannerTitle = إعدادات As Built Report + ReportConfigFolder = أدخل المسار الكامل للمجلد لاستخدامه لتخزين ملفات تكوين وحدة التقرير والنصوص البرمجية المخصصة [{0}] + OverwriteReportConfig = يوجد بالفعل ملف تكوين وحدة التقرير لـ {0} في المجلد المحدد. هل تريد الكتابة فوقه؟ (y/N) + CopyFile = نسخ '{0}' إلى '{1}'. + OverwriteFile = نسخ '{0}' إلى '{1}'. الكتابة فوق الملف الموجود. + SaveAsBuiltConfig = هل تريد حفظ ملف تكوين الوحدة الأساسية لـ As Built Report؟ (Y/n) + AsBuiltName = أدخل اسمًا لملف تكوين As Built Report [AsBuiltReport] + AsBuiltExportPath = أدخل المسار لحفظ ملف تكوين As Built Report [{0}] + ConfigFolder = إنشاء مجلد تكوين As Built Report '{0}'. + SaveConfig = حفظ ملف تكوين As Built Report '{0}.json' إلى المسار '{1}'. + NotSaved = لم يتم حفظ ملف تكوين As Built Report. +'@ +} diff --git a/AsBuiltReport.Core/Language/ar-SA/New-AsBuiltReport.psd1 b/AsBuiltReport.Core/Language/ar-SA/New-AsBuiltReport.psd1 new file mode 100644 index 0000000..bdfd1f0 --- /dev/null +++ b/AsBuiltReport.Core/Language/ar-SA/New-AsBuiltReport.psd1 @@ -0,0 +1,40 @@ +# culture = 'ar-SA' +ConvertFrom-StringData @' + PwshISE = لا يمكن تشغيل AsBuiltReport من Windows PowerShell ISE. يرجى استخدام نافذة أوامر PowerShell بدلاً من ذلك. + Password = كلمة المرور للمستخدم {0} + OutputFolderPath = OutputFolderPath '{0}' ليس مسار مجلد صالح. + LoadConfig = تحميل تكوين As Built Report من {0}. + NoConfigFound = تعذر العثور على تكوين As Built Report في المسار '{0}'. + GeneratingReport = إنشاء تكوين As Built Report جديد. + StyleScriptNotFound = تعذر العثور على نص نمط التقرير في المسار '{0}'. + ReportModuleNotFound = تعذر العثور على ملف تكوين التقرير {0} في المسار '{1}'. + LoadingReportConfig = تحميل ملف تكوين التقرير {0} من المسار '{1}'. + ReportConfigNotFound = لم يتم العثور على تكوين التقرير في مسار الوحدة '{0}'. + SetReportFileName = تعيين اسم ملف التقرير إلى '{0}'. + EmailBannerTitle = بيانات اعتماد خادم البريد الإلكتروني + EmailCredentials = يرجى إدخال بيانات الاعتماد لـ {0}. + InstalledModule = AsBuiltReport.Core {0} مثبت حالياً. + AvailableModule = AsBuiltReport.Core {0} متاح. + UpdateModule = قم بتشغيل 'Update-Module -Name AsBuiltReport.Core -Force' لتثبيت الإصدار الأحدث. + ReportGenerating = يرجى الانتظار بينما يتم إنشاء تقرير {0} As Built. + ReportInitializing = > تهيئة إطار عمل التقرير... + DocumentStyle = > تحميل نمط المستند... + TargetSystem = > الاتصال بالنظام المستهدف وجمع البيانات... + ExecutionFailed = فشل تنفيذ وحدة التقرير: {0} + BuildingDocument = > بناء هيكل المستند... + ExportingDocument = > تصدير المستند... + Failed = [فشل] فشل إنشاء التقرير + ReportStyleScript = تنفيذ نص نمط التقرير من المسار '{0}'. + InteractiveAuth = تم تمكين المصادقة التفاعلية. يرجى التحقق من نوافذ المصادقة للمصادقة على النظام المستهدف. + OutputFolder = تم حفظ {0} As Built Report '{1}' في '{2}'. + ReportModuleInfo1 = التوثيق: https://github.com/AsBuiltReport/AsBuiltReport.{0} + ReportModuleInfo2 = المشاكل أو الإبلاغ عن الأخطاء: https://github.com/AsBuiltReport/AsBuiltReport.{0}/issues + ReportModuleInfo3 = لا تنس تحديث ملف تكوين التقرير الخاص بك بعد كل إصدار جديد: https://www.asbuiltreport.com/user-guide/new-asbuiltreportconfig/ + ProjectWebsite = يرجى الرجوع إلى موقع مشروع AsBuiltReport لمزيد من المعلومات التفصيلية: https://www.asbuiltreport.com + CommunityProject = AsBuiltReport هو مشروع مفتوح المصدر تحتفظ به المجتمع. ليس له رعاية أو تأييد أو ارتباط مع أي موردي تكنولوجيا أو موظفيهم أو الشركات التابعة لهم. + ReportModuleInstalled = {0} {1} مثبت حالياً. + ReportModuleAvailable = {0} {1} متاح. + ReportModuleUpdate = قم بتشغيل 'Update-Module -Name {0} -Force' لتثبيت الإصدار الأحدث. + RequiredModuleNotInstalled = {0} {1} أو أعلى مطلوب. قم بتشغيل 'Install-Module -Name {0} -RequiredVersion {1} -AllowClobber' لتثبيت الوحدة المطلوبة. + RequiredModuleTooOld = {0} {1} مثبت حالياً. {0} {2} أو أعلى مطلوب. قم بتشغيل 'Update-Module -Name {0} -RequiredVersion {2} -Force' للتحديث إلى الإصدار المطلوب. +'@ diff --git a/AsBuiltReport.Core/Language/ar-SA/New-AsBuiltReportConfig.psd1 b/AsBuiltReport.Core/Language/ar-SA/New-AsBuiltReportConfig.psd1 new file mode 100644 index 0000000..0ba5c46 --- /dev/null +++ b/AsBuiltReport.Core/Language/ar-SA/New-AsBuiltReportConfig.psd1 @@ -0,0 +1,11 @@ +# culture = 'ar-SA' +ConvertFrom-StringData @' + FolderNotExist = المجلد '{0}' غير موجود. يرجى إنشاء المجلد وتشغيل New-AsBuiltReportConfig مرة أخرى. + ProcessConfig = معالجة ملف تكوين التقرير {0} من الوحدة {1}، الإصدار {2}. + CopyConfig = نسخ ملف تكوين التقرير '{0}' إلى '{1}'. + CopyModuleConfig = نسخ ملف تكوين التقرير {0} '{1}' إلى '{2}'. + CreateConfig = تم إنشاء ملف تكوين التقرير {0} '{1}.json' في '{2}'. + OverWriteConfig = نسخ ملف تكوين التقرير '{0}' إلى '{1}'. الكتابة فوق الملف الموجود. + ForceOverwrite = ملف تكوين التقرير {0} '{1}.json' موجود بالفعل في '{2}'. استخدم '-Force' للكتابة فوق الملف الموجود. + ConfigNotFound = لم يتم العثور على ملف تكوين التقرير في مسار الوحدة '{0}'. +'@ diff --git a/AsBuiltReport.Core/Language/cs-CZ/AsBuiltReportCoreStyle.psd1 b/AsBuiltReport.Core/Language/cs-CZ/AsBuiltReportCoreStyle.psd1 new file mode 100644 index 0000000..e73e139 --- /dev/null +++ b/AsBuiltReport.Core/Language/cs-CZ/AsBuiltReportCoreStyle.psd1 @@ -0,0 +1,11 @@ +# culture = 'cs-CZ' +ConvertFrom-StringData @' + Footer = Strana + Logo = Logo AsBuiltReport + CoverPageWarning = Nelze zobrazit obrázek titulní stránky. Nastavte prosím 'ShowCoverPageImage' na 'false' v konfiguračním souboru JSON sestavy, abyste se tomuto chybě vyhnuli. + CoverPage = Titulní strana + Author = Autor: + Date = Datum: + Version = Verze: + TOC = Obsah +'@ diff --git a/AsBuiltReport.Core/Language/cs-CZ/New-AsBuiltConfig.psd1 b/AsBuiltReport.Core/Language/cs-CZ/New-AsBuiltConfig.psd1 new file mode 100644 index 0000000..21a7192 --- /dev/null +++ b/AsBuiltReport.Core/Language/cs-CZ/New-AsBuiltConfig.psd1 @@ -0,0 +1,58 @@ +# culture = 'cs-CZ' +@{ + +# As Built Report Information +ReportInfo = ConvertFrom-StringData @' + BannerTitle = Informace o As Built Report + ReportAuthor = Zadejte jméno autora této sestavy As Built Report [{0}] +'@ + +# Company Configuration +CompanyConfig = ConvertFrom-StringData @' + BannerTitle = Informace o společnosti + CompanyInfo = Chcete zadat informace o společnosti pro sestavu As Built Report? (y/N) + CompanyFullName = Zadejte úplný název společnosti + CompanyShortName = Zadejte zkrácený název společnosti + CompanyContact = Zadejte kontaktní osobu společnosti + CompanyEmail = Zadejte e-mailovou adresu společnosti + CompanyPhone = Zadejte telefonní číslo společnosti + CompanyAddress = Zadejte adresu společnosti +'@ + +# Email Configuration +EmailConfig = ConvertFrom-StringData @' + BannerTitle = Konfigurace e-mailu + ConfigureMailSettings = Chcete zadat konfiguraci SMTP? (y/N) + MailServer = Zadejte FQDN / IP adresu poštovního serveru + EmptyMailServerAddress = Adresa poštovního serveru nesmí být prázdná. Zadejte platnou FQDN / IP adresu poštovního serveru. + InvalidMailServer = '{0}' není platná FQDN nebo IP adresa. Zadejte platnou FQDN / IP adresu poštovního serveru. + MailServerPort587 = Zadejte číslo portu poštovního serveru [587] + InvalidMailServerPort587 = Neplatné číslo portu. Zadejte číslo mezi 1 a 65535 nebo stiskněte Enter pro výchozí hodnotu [587]. + MailServerPort25 = Zadejte číslo portu poštovního serveru [25] + InvalidMailServerPort25 = Neplatné číslo portu. Zadejte číslo mezi 1 a 65535 nebo stiskněte Enter pro výchozí hodnotu [25]. + MailServerUseSSL = Použít SSL pro připojení k poštovnímu serveru? (y/N) + MailCredentials = Vyžaduje poštovní server ověření? (y/N) + MailFrom = Zadejte e-mailovou adresu odesílatele + MailTo = Zadejte e-mailovou adresu příjemce + EmptyEmail = E-mailová adresa nesmí být prázdná. Zadejte platnou e-mailovou adresu. + InvalidEmail = '{0}' není platná e-mailová adresa. Zadejte platnou e-mailovou adresu. + AnotherRecipient = Chcete zadat dalšího příjemce? (y/N) + MailBodyPrompt = Zadejte obsah těla e-mailové zprávy + MailBody = Sestava As Built Report připojena +'@ + +# Report Configuration +ReportConfig = ConvertFrom-StringData @' + BannerTitle = Konfigurace As Built Report + ReportConfigFolder = Zadejte úplnou cestu ke složce, která se má použít pro ukládání konfiguračních souborů modulu sestav a vlastních skriptů stylů [{0}] + OverwriteReportConfig = Konfigurační soubor modulu sestav pro {0} již v zadané složce existuje. Chcete jej přepsat? (y/N) + CopyFile = Kopírování '{0}' do '{1}'. + OverwriteFile = Kopírování '{0}' do '{1}'. Přepsání existujícího souboru. + SaveAsBuiltConfig = Chcete uložit konfigurační soubor základního modulu As Built Report? (Y/n) + AsBuiltName = Zadejte název konfiguračního souboru As Built Report [AsBuiltReport] + AsBuiltExportPath = Zadejte cestu pro uložení konfiguračního souboru As Built Report [{0}] + ConfigFolder = Vytváření konfigurační složky As Built Report '{0}'. + SaveConfig = Ukládání konfiguračního souboru As Built Report '{0}.json' do cesty '{1}'. + NotSaved = Konfigurační soubor As Built Report nebyl uložen. +'@ +} diff --git a/AsBuiltReport.Core/Language/cs-CZ/New-AsBuiltReport.psd1 b/AsBuiltReport.Core/Language/cs-CZ/New-AsBuiltReport.psd1 new file mode 100644 index 0000000..89359c6 --- /dev/null +++ b/AsBuiltReport.Core/Language/cs-CZ/New-AsBuiltReport.psd1 @@ -0,0 +1,40 @@ +# culture = 'cs-CZ' +ConvertFrom-StringData @' + PwshISE = AsBuiltReport nelze spustit z Windows PowerShell ISE. Použijte místo toho příkazové okno PowerShell. + Password = Heslo pro uživatele {0} + OutputFolderPath = OutputFolderPath '{0}' není platná cesta ke složce. + LoadConfig = Načítání konfigurace As Built Report z {0}. + NoConfigFound = Nelze najít konfiguraci As Built Report v cestě '{0}'. + GeneratingReport = Generování nové konfigurace As Built Report. + StyleScriptNotFound = Nelze najít skript stylu sestavy v cestě '{0}'. + ReportModuleNotFound = Nelze najít konfigurační soubor sestavy {0} v cestě '{1}'. + LoadingReportConfig = Načítání konfiguračního souboru sestavy {0} z cesty '{1}'. + ReportConfigNotFound = Konfigurace sestavy nebyla nalezena v cestě modulu '{0}'. + SetReportFileName = Nastavení názvu souboru sestavy na '{0}'. + EmailBannerTitle = Přihlašovací údaje e-mailového serveru + EmailCredentials = Zadejte přihlašovací údaje pro {0}. + InstalledModule = AsBuiltReport.Core {0} je aktuálně nainstalován. + AvailableModule = AsBuiltReport.Core {0} je k dispozici. + UpdateModule = Spusťte 'Update-Module -Name AsBuiltReport.Core -Force' pro instalaci nejnovější verze. + ReportGenerating = Počkejte prosím, než se vygeneruje sestava {0} As Built. + ReportInitializing = > Inicializace frameworku sestavy... + DocumentStyle = > Načítání stylu dokumentu... + TargetSystem = > Připojování k cílovému systému a shromažďování dat... + ExecutionFailed = Spuštění modulu sestavy se nezdařilo: {0} + BuildingDocument = > Vytváření struktury dokumentu... + ExportingDocument = > Export dokumentu... + Failed = [SELHALO] Generování sestavy se nezdařilo + ReportStyleScript = Spouštění skriptu stylu sestavy z cesty '{0}'. + InteractiveAuth = Interaktivní ověřování je povoleno. Zkontrolujte okna ověřování pro ověření v cílovém systému. + OutputFolder = {0} As Built Report '{1}' byl uložen do '{2}'. + ReportModuleInfo1 = Dokumentace: https://github.com/AsBuiltReport/AsBuiltReport.{0} + ReportModuleInfo2 = Problémy nebo hlášení chyb: https://github.com/AsBuiltReport/AsBuiltReport.{0}/issues + ReportModuleInfo3 = Nezapomeňte aktualizovat konfigurační soubor sestavy po každém novém vydání verze: https://www.asbuiltreport.com/user-guide/new-asbuiltreportconfig/ + ProjectWebsite = Podrobnější informace naleznete na webových stránkách projektu AsBuiltReport: https://www.asbuiltreport.com + CommunityProject = AsBuiltReport je open source projekt udržovaný komunitou. Nemá žádné sponzorství, podporu ani příslušnost k žádným dodavatelům technologií, jejich zaměstnancům nebo přidruženým osobám. + ReportModuleInstalled = {0} {1} je aktuálně nainstalován. + ReportModuleAvailable = {0} {1} je k dispozici. + ReportModuleUpdate = Spusťte 'Update-Module -Name {0} -Force' pro instalaci nejnovější verze. + RequiredModuleNotInstalled = Je vyžadován {0} {1} nebo vyšší. Spusťte 'Install-Module -Name {0} -RequiredVersion {1} -AllowClobber' pro instalaci požadovaného modulu. + RequiredModuleTooOld = {0} {1} je aktuálně nainstalován. Je vyžadován {0} {2} nebo vyšší. Spusťte 'Update-Module -Name {0} -RequiredVersion {2} -Force' pro aktualizaci na požadovanou verzi. +'@ diff --git a/AsBuiltReport.Core/Language/cs-CZ/New-AsBuiltReportConfig.psd1 b/AsBuiltReport.Core/Language/cs-CZ/New-AsBuiltReportConfig.psd1 new file mode 100644 index 0000000..e21d650 --- /dev/null +++ b/AsBuiltReport.Core/Language/cs-CZ/New-AsBuiltReportConfig.psd1 @@ -0,0 +1,11 @@ +# culture = 'cs-CZ' +ConvertFrom-StringData @' + FolderNotExist = Složka '{0}' neexistuje. Vytvořte prosím složku a spusťte New-AsBuiltReportConfig znovu. + ProcessConfig = Zpracovávání konfiguračního souboru sestavy {0} z modulu {1}, verze {2}. + CopyConfig = Kopírování konfiguračního souboru sestavy '{0}' do '{1}'. + CopyModuleConfig = Kopírování konfiguračního souboru sestavy {0} '{1}' do '{2}'. + CreateConfig = Konfigurační soubor sestavy {0} '{1}.json' vytvořen v '{2}'. + OverWriteConfig = Kopírování konfiguračního souboru sestavy '{0}' do '{1}'. Přepsání existujícího souboru. + ForceOverwrite = Konfigurační soubor sestavy {0} '{1}.json' již existuje v '{2}'. Použijte '-Force' pro přepsání existujícího souboru. + ConfigNotFound = Konfigurační soubor sestavy nebyl nalezen v cestě modulu '{0}'. +'@ diff --git a/AsBuiltReport.Core/Language/da-DK/AsBuiltReportCoreStyle.psd1 b/AsBuiltReport.Core/Language/da-DK/AsBuiltReportCoreStyle.psd1 new file mode 100644 index 0000000..bd62653 --- /dev/null +++ b/AsBuiltReport.Core/Language/da-DK/AsBuiltReportCoreStyle.psd1 @@ -0,0 +1,11 @@ +# culture = 'da-DK' +ConvertFrom-StringData @' + Footer = Side + Logo = AsBuiltReport Logo + CoverPageWarning = Kan ikke vise forsidebillede. Indstil venligst 'ShowCoverPageImage' til 'false' i rapportens JSON-konfigurationsfil for at undgå denne fejl. + CoverPage = Forside + Author = Forfatter: + Date = Dato: + Version = Version: + TOC = Indholdsfortegnelse +'@ diff --git a/AsBuiltReport.Core/Language/da-DK/New-AsBuiltConfig.psd1 b/AsBuiltReport.Core/Language/da-DK/New-AsBuiltConfig.psd1 new file mode 100644 index 0000000..8aae591 --- /dev/null +++ b/AsBuiltReport.Core/Language/da-DK/New-AsBuiltConfig.psd1 @@ -0,0 +1,58 @@ +# culture = 'da-DK' +@{ + +# As Built Report Information +ReportInfo = ConvertFrom-StringData @' + BannerTitle = As Built Report Information + ReportAuthor = Indtast navnet på forfatteren til denne As Built Report [{0}] +'@ + +# Company Configuration +CompanyConfig = ConvertFrom-StringData @' + BannerTitle = Virksomhedsinformation + CompanyInfo = Vil du indtaste virksomhedsinformation til As Built Report? (y/N) + CompanyFullName = Indtast det fulde virksomhedsnavn + CompanyShortName = Indtast virksomhedens korte navn + CompanyContact = Indtast virksomhedskontakt + CompanyEmail = Indtast virksomhedens e-mailadresse + CompanyPhone = Indtast virksomhedens telefonnummer + CompanyAddress = Indtast virksomhedsadresse +'@ + +# Email Configuration +EmailConfig = ConvertFrom-StringData @' + BannerTitle = E-mailkonfiguration + ConfigureMailSettings = Vil du indtaste SMTP-konfiguration? (y/N) + MailServer = Indtast mailserverens FQDN / IP-adresse + EmptyMailServerAddress = Mailserveradressen må ikke være tom. Indtast venligst en gyldig mailserver FQDN / IP-adresse. + InvalidMailServer = '{0}' er ikke en gyldig FQDN eller IP-adresse. Indtast venligst en gyldig mailserver FQDN / IP-adresse. + MailServerPort587 = Indtast mailserverens portnummer [587] + InvalidMailServerPort587 = Ugyldigt portnummer. Indtast venligst et tal mellem 1 og 65535, eller tryk på Enter for standardværdien [587]. + MailServerPort25 = Indtast mailserverens portnummer [25] + InvalidMailServerPort25 = Ugyldigt portnummer. Indtast venligst et tal mellem 1 og 65535, eller tryk på Enter for standardværdien [25]. + MailServerUseSSL = Brug SSL til mailserverforbindelse? (y/N) + MailCredentials = Kræver mailserveren godkendelse? (y/N) + MailFrom = Indtast afsenderens e-mailadresse + MailTo = Indtast modtagerens e-mailadresse + EmptyEmail = E-mailadressen må ikke være tom. Indtast venligst en gyldig e-mailadresse. + InvalidEmail = '{0}' er ikke en gyldig e-mailadresse. Indtast venligst en gyldig e-mailadresse. + AnotherRecipient = Vil du indtaste en anden modtager? (y/N) + MailBodyPrompt = Indtast indholdet af e-mailbeskedens brødtekst + MailBody = As Built Report vedhæftet +'@ + +# Report Configuration +ReportConfig = ConvertFrom-StringData @' + BannerTitle = As Built Report Konfiguration + ReportConfigFolder = Indtast den fulde sti til mappen, der skal bruges til at gemme rapportmodulkonfigurationsfiler og brugerdefinerede typografiskrip ter [{0}] + OverwriteReportConfig = En rapportmodulkonfigurationsfil til {0} findes allerede i den angivne mappe. Vil du overskrive den? (y/N) + CopyFile = Kopierer '{0}' til '{1}'. + OverwriteFile = Kopierer '{0}' til '{1}'. Overskriver eksisterende fil. + SaveAsBuiltConfig = Vil du gemme As Built Report kernemodul konfigurationsfilen? (Y/n) + AsBuiltName = Indtast et navn til As Built Report konfigurationsfilen [AsBuiltReport] + AsBuiltExportPath = Indtast stien til at gemme As Built Report konfigurationsfilen [{0}] + ConfigFolder = Opretter As Built Report konfigurationsmappe '{0}'. + SaveConfig = Gemmer As Built Report konfigurationsfil '{0}.json' til sti '{1}'. + NotSaved = As Built Report konfigurationsfilen blev ikke gemt. +'@ +} diff --git a/AsBuiltReport.Core/Language/da-DK/New-AsBuiltReport.psd1 b/AsBuiltReport.Core/Language/da-DK/New-AsBuiltReport.psd1 new file mode 100644 index 0000000..2dfa442 --- /dev/null +++ b/AsBuiltReport.Core/Language/da-DK/New-AsBuiltReport.psd1 @@ -0,0 +1,40 @@ +# culture = 'da-DK' +ConvertFrom-StringData @' + PwshISE = AsBuiltReport kan ikke køres fra Windows PowerShell ISE. Brug venligst et PowerShell-kommandovindue i stedet. + Password = Adgangskode for bruger {0} + OutputFolderPath = OutputFolderPath '{0}' er ikke en gyldig mappesti. + LoadConfig = Indlæser As Built Report-konfiguration fra {0}. + NoConfigFound = Kunne ikke finde As Built Report-konfiguration i stien '{0}'. + GeneratingReport = Genererer ny As Built Report-konfiguration. + StyleScriptNotFound = Kunne ikke finde rapportstilscript i stien '{0}'. + ReportModuleNotFound = Kunne ikke finde {0} rapportkonfigurationsfil i stien '{1}'. + LoadingReportConfig = Indlæser {0} rapportkonfigurationsfil fra stien '{1}'. + ReportConfigNotFound = Rapportkonfiguration ikke fundet i modulstien '{0}'. + SetReportFileName = Indstiller rapportfilnavn til '{0}'. + EmailBannerTitle = E-mail-serverlegitimationsoplysninger + EmailCredentials = Indtast venligst legitimationsoplysninger for {0}. + InstalledModule = AsBuiltReport.Core {0} er i øjeblikket installeret. + AvailableModule = AsBuiltReport.Core {0} er tilgængelig. + UpdateModule = Kør 'Update-Module -Name AsBuiltReport.Core -Force' for at installere den nyeste version. + ReportGenerating = Vent venligst, mens {0} As Built Report genereres. + ReportInitializing = > Initialiserer rapportramme... + DocumentStyle = > Indlæser dokumentstil... + TargetSystem = > Opretter forbindelse til målsystem og indsamler data... + ExecutionFailed = Udførelse af rapportmodul mislykkedes: {0} + BuildingDocument = > Opbygger dokumentstruktur... + ExportingDocument = > Eksporterer dokument... + Failed = [MISLYKKET] Rapportgenerering mislykkedes + ReportStyleScript = Udfører rapportstilscript fra stien '{0}'. + InteractiveAuth = Interaktiv godkendelse er aktiveret. Tjek venligst godkendelsesvinduer for at godkende til dit målsystem. + OutputFolder = {0} As Built Report '{1}' er blevet gemt i '{2}'. + ReportModuleInfo1 = Dokumentation: https://github.com/AsBuiltReport/AsBuiltReport.{0} + ReportModuleInfo2 = Problemer eller fejlrapportering: https://github.com/AsBuiltReport/AsBuiltReport.{0}/issues + ReportModuleInfo3 = Glem ikke at opdatere din rapportkonfigurationsfil efter hver ny versionsudgivelse: https://www.asbuiltreport.com/user-guide/new-asbuiltreportconfig/ + ProjectWebsite = Se venligst AsBuiltReport-projektets websted for mere detaljerede oplysninger: https://www.asbuiltreport.com + CommunityProject = AsBuiltReport er et fællesskabsvedligeholdt open source-projekt. Det har ingen sponsorering, godkendelse eller tilknytning til nogen teknologileverandører, deres ansatte eller associerede virksomheder. + ReportModuleInstalled = {0} {1} er i øjeblikket installeret. + ReportModuleAvailable = {0} {1} er tilgængelig. + ReportModuleUpdate = Kør 'Update-Module -Name {0} -Force' for at installere den nyeste version. + RequiredModuleNotInstalled = {0} {1} eller højere er påkrævet. Kør 'Install-Module -Name {0} -RequiredVersion {1} -AllowClobber' for at installere den påkrævede modul. + RequiredModuleTooOld = {0} {1} er i øjeblikket installeret. {0} {2} eller højere er påkrævet. Kør 'Update-Module -Name {0} -RequiredVersion {2} -Force' for at opdatere til den påkrævede version. +'@ diff --git a/AsBuiltReport.Core/Language/da-DK/New-AsBuiltReportConfig.psd1 b/AsBuiltReport.Core/Language/da-DK/New-AsBuiltReportConfig.psd1 new file mode 100644 index 0000000..0c62fcc --- /dev/null +++ b/AsBuiltReport.Core/Language/da-DK/New-AsBuiltReportConfig.psd1 @@ -0,0 +1,11 @@ +# culture = 'da-DK' +ConvertFrom-StringData @' + FolderNotExist = Mappen '{0}' findes ikke. Opret venligst mappen og kør New-AsBuiltReportConfig igen. + ProcessConfig = Behandler {0} rapportkonfigurationsfil fra modul {1}, version {2}. + CopyConfig = Kopierer rapportkonfigurationsfil '{0}' til '{1}'. + CopyModuleConfig = Kopierer {0} rapportkonfigurationsfil '{1}' til '{2}'. + CreateConfig = {0} rapportkonfigurationsfil '{1}.json' oprettet i '{2}'. + OverWriteConfig = Kopierer rapportkonfigurationsfil '{0}' til '{1}'. Overskriver eksisterende fil. + ForceOverwrite = {0} rapportkonfigurationsfil '{1}.json' findes allerede i '{2}'. Brug '-Force' til at overskrive eksisterende fil. + ConfigNotFound = Rapportkonfigurationsfil ikke fundet i modulsti '{0}'. +'@ diff --git a/AsBuiltReport.Core/Language/de-DE/AsBuiltReportCoreStyle.psd1 b/AsBuiltReport.Core/Language/de-DE/AsBuiltReportCoreStyle.psd1 new file mode 100644 index 0000000..79a9982 --- /dev/null +++ b/AsBuiltReport.Core/Language/de-DE/AsBuiltReportCoreStyle.psd1 @@ -0,0 +1,11 @@ +# culture = 'de-DE' +ConvertFrom-StringData @' + Footer = Seite + Logo = AsBuiltReport Logo + CoverPageWarning = Deckblattbild kann nicht angezeigt werden. Bitte setzen Sie 'ShowCoverPageImage' in der JSON-Konfigurationsdatei des Berichts auf 'false', um diesen Fehler zu vermeiden. + CoverPage = Deckblatt + Author = Autor: + Date = Datum: + Version = Version: + TOC = Inhaltsverzeichnis +'@ diff --git a/AsBuiltReport.Core/Language/de-DE/New-AsBuiltConfig.psd1 b/AsBuiltReport.Core/Language/de-DE/New-AsBuiltConfig.psd1 new file mode 100644 index 0000000..b88ffe0 --- /dev/null +++ b/AsBuiltReport.Core/Language/de-DE/New-AsBuiltConfig.psd1 @@ -0,0 +1,58 @@ +# culture = 'de-DE' +@{ + +# As Built Report Information +ReportInfo = ConvertFrom-StringData @' + BannerTitle = As Built Report Informationen + ReportAuthor = Geben Sie den Namen des Autors für diesen As Built Report ein [{0}] +'@ + +# Company Configuration +CompanyConfig = ConvertFrom-StringData @' + BannerTitle = Unternehmensinformationen + CompanyInfo = Möchten Sie Unternehmensinformationen für den As Built Report eingeben? (y/N) + CompanyFullName = Geben Sie den vollständigen Unternehmensnamen ein + CompanyShortName = Geben Sie den Kurznamen des Unternehmens ein + CompanyContact = Geben Sie den Unternehmenskontakt ein + CompanyEmail = Geben Sie die E-Mail-Adresse des Unternehmens ein + CompanyPhone = Geben Sie die Telefonnummer des Unternehmens ein + CompanyAddress = Geben Sie die Unternehmensadresse ein +'@ + +# Email Configuration +EmailConfig = ConvertFrom-StringData @' + BannerTitle = E-Mail-Konfiguration + ConfigureMailSettings = Möchten Sie die SMTP-Konfiguration eingeben? (y/N) + MailServer = Geben Sie den FQDN / die IP-Adresse des Mailservers ein + EmptyMailServerAddress = Die Mailserveradresse darf nicht leer sein. Bitte geben Sie einen gültigen FQDN / eine gültige IP-Adresse des Mailservers ein. + InvalidMailServer = '{0}' ist kein gültiger FQDN oder keine gültige IP-Adresse. Bitte geben Sie einen gültigen FQDN / eine gültige IP-Adresse des Mailservers ein. + MailServerPort587 = Geben Sie die Portnummer des Mailservers ein [587] + InvalidMailServerPort587 = Ungültige Portnummer. Bitte geben Sie eine Zahl zwischen 1 und 65535 ein oder drücken Sie die Eingabetaste für den Standard [587]. + MailServerPort25 = Geben Sie die Portnummer des Mailservers ein [25] + InvalidMailServerPort25 = Ungültige Portnummer. Bitte geben Sie eine Zahl zwischen 1 und 65535 ein oder drücken Sie die Eingabetaste für den Standard [25]. + MailServerUseSSL = SSL für Mailserververbindung verwenden? (y/N) + MailCredentials = Ist eine Mailserver-Authentifizierung erforderlich? (y/N) + MailFrom = Geben Sie die E-Mail-Adresse des Absenders ein + MailTo = Geben Sie die E-Mail-Adresse des Empfängers ein + EmptyEmail = Die E-Mail-Adresse darf nicht leer sein. Bitte geben Sie eine gültige E-Mail-Adresse ein. + InvalidEmail = '{0}' ist keine gültige E-Mail-Adresse. Bitte geben Sie eine gültige E-Mail-Adresse ein. + AnotherRecipient = Möchten Sie einen weiteren Empfänger eingeben? (y/N) + MailBodyPrompt = Geben Sie den Inhalt der E-Mail-Nachricht ein + MailBody = As Built Report angehängt +'@ + +# Report Configuration +ReportConfig = ConvertFrom-StringData @' + BannerTitle = As Built Report Konfiguration + ReportConfigFolder = Geben Sie den vollständigen Pfad des Ordners ein, der zum Speichern von Berichtsmodulkonfigurationsdateien und benutzerdefinierten Stilskripten verwendet werden soll [{0}] + OverwriteReportConfig = Eine Berichtsmodulkonfigurationsdatei für {0} existiert bereits im angegebenen Ordner. Möchten Sie sie überschreiben? (y/N) + CopyFile = '{0}' wird nach '{1}' kopiert. + OverwriteFile = '{0}' wird nach '{1}' kopiert. Vorhandene Datei wird überschrieben. + SaveAsBuiltConfig = Möchten Sie die As Built Report Kernmodulkonfigurationsdatei speichern? (Y/n) + AsBuiltName = Geben Sie einen Namen für die As Built Report Konfigurationsdatei ein [AsBuiltReport] + AsBuiltExportPath = Geben Sie den Pfad zum Speichern der As Built Report Konfigurationsdatei ein [{0}] + ConfigFolder = As Built Report Konfigurationsordner '{0}' wird erstellt. + SaveConfig = As Built Report Konfigurationsdatei '{0}.json' wird im Pfad '{1}' gespeichert. + NotSaved = As Built Report Konfigurationsdatei wurde nicht gespeichert. +'@ +} diff --git a/AsBuiltReport.Core/Language/de-DE/New-AsBuiltReport.psd1 b/AsBuiltReport.Core/Language/de-DE/New-AsBuiltReport.psd1 new file mode 100644 index 0000000..b7b81f9 --- /dev/null +++ b/AsBuiltReport.Core/Language/de-DE/New-AsBuiltReport.psd1 @@ -0,0 +1,40 @@ +# culture = 'de-DE' +ConvertFrom-StringData @' + PwshISE = AsBuiltReport kann nicht von Windows PowerShell ISE ausgeführt werden. Bitte verwenden Sie stattdessen ein PowerShell-Befehlsfenster. + Password = Passwort für Benutzer {0} + OutputFolderPath = OutputFolderPath '{0}' ist kein gültiger Ordnerpfad. + LoadConfig = Lade As Built Report-Konfiguration von {0}. + NoConfigFound = As Built Report-Konfiguration konnte im Pfad '{0}' nicht gefunden werden. + GeneratingReport = Generiere neue As Built Report-Konfiguration. + StyleScriptNotFound = Report-Stilskript konnte im Pfad '{0}' nicht gefunden werden. + ReportModuleNotFound = {0} Report-Konfigurationsdatei konnte im Pfad '{1}' nicht gefunden werden. + LoadingReportConfig = Lade {0} Report-Konfigurationsdatei vom Pfad '{1}'. + ReportConfigNotFound = Report-Konfiguration im Modulpfad '{0}' nicht gefunden. + SetReportFileName = Setze Report-Dateiname auf '{0}'. + EmailBannerTitle = E-Mail-Server-Anmeldeinformationen + EmailCredentials = Bitte geben Sie die Anmeldeinformationen für {0} ein. + InstalledModule = AsBuiltReport.Core {0} ist derzeit installiert. + AvailableModule = AsBuiltReport.Core {0} ist verfügbar. + UpdateModule = Führen Sie 'Update-Module -Name AsBuiltReport.Core -Force' aus, um die neueste Version zu installieren. + ReportGenerating = Bitte warten Sie, während der {0} As Built Report generiert wird. + ReportInitializing = > Initialisiere Report-Framework... + DocumentStyle = > Lade Dokumentstil... + TargetSystem = > Verbinde mit Zielsystem und sammle Daten... + ExecutionFailed = Ausführung des Report-Moduls fehlgeschlagen: {0} + BuildingDocument = > Erstelle Dokumentstruktur... + ExportingDocument = > Exportiere Dokument... + Failed = [FEHLER] Report-Generierung fehlgeschlagen + ReportStyleScript = Führe Report-Stilskript vom Pfad '{0}' aus. + InteractiveAuth = Interaktive Authentifizierung ist aktiviert. Bitte überprüfen Sie die Authentifizierungsfenster, um sich bei Ihrem Zielsystem zu authentifizieren. + OutputFolder = {0} As Built Report '{1}' wurde in '{2}' gespeichert. + ReportModuleInfo1 = Dokumentation: https://github.com/AsBuiltReport/AsBuiltReport.{0} + ReportModuleInfo2 = Probleme oder Fehlerberichte: https://github.com/AsBuiltReport/AsBuiltReport.{0}/issues + ReportModuleInfo3 = Vergessen Sie nicht, Ihre Report-Konfigurationsdatei nach jeder neuen Versionsveröffentlichung zu aktualisieren: https://www.asbuiltreport.com/user-guide/new-asbuiltreportconfig/ + ProjectWebsite = Weitere detaillierte Informationen finden Sie auf der AsBuiltReport-Projektwebsite: https://www.asbuiltreport.com + CommunityProject = AsBuiltReport ist ein von der Community gepflegtes Open-Source-Projekt. Es hat keine Förderung, Unterstützung oder Verbindung zu Technologieanbietern, deren Mitarbeitern oder verbundenen Unternehmen. + ReportModuleInstalled = {0} {1} ist derzeit installiert. + ReportModuleAvailable = {0} {1} ist verfügbar. + ReportModuleUpdate = Führen Sie 'Update-Module -Name {0} -Force' aus, um die neueste Version zu installieren. + RequiredModuleNotInstalled = {0} {1} oder höher ist erforderlich. Führen Sie 'Install-Module -Name {0} -RequiredVersion {1} -AllowClobber' aus, um das erforderliche Modul zu installieren. + RequiredModuleTooOld = {0} {1} ist derzeit installiert. {0} {2} oder höher ist erforderlich. Führen Sie 'Update-Module -Name {0} -RequiredVersion {2} -Force' aus, um auf die erforderliche Version zu aktualisieren. +'@ diff --git a/AsBuiltReport.Core/Language/de-DE/New-AsBuiltReportConfig.psd1 b/AsBuiltReport.Core/Language/de-DE/New-AsBuiltReportConfig.psd1 new file mode 100644 index 0000000..f4062d9 --- /dev/null +++ b/AsBuiltReport.Core/Language/de-DE/New-AsBuiltReportConfig.psd1 @@ -0,0 +1,11 @@ +# culture = 'de-DE' +ConvertFrom-StringData @' + FolderNotExist = Der Ordner '{0}' existiert nicht. Bitte erstellen Sie den Ordner und führen Sie New-AsBuiltReportConfig erneut aus. + ProcessConfig = Verarbeite {0} Berichtskonfigurationsdatei aus Modul {1}, Version {2}. + CopyConfig = Kopiere Berichtskonfigurationsdatei '{0}' nach '{1}'. + CopyModuleConfig = Kopiere {0} Berichtskonfigurationsdatei '{1}' nach '{2}'. + CreateConfig = {0} Berichtskonfigurationsdatei '{1}.json' wurde in '{2}' erstellt. + OverWriteConfig = Kopiere Berichtskonfigurationsdatei '{0}' nach '{1}'. Vorhandene Datei wird überschrieben. + ForceOverwrite = {0} Berichtskonfigurationsdatei '{1}.json' existiert bereits in '{2}'. Verwenden Sie '-Force', um die vorhandene Datei zu überschreiben. + ConfigNotFound = Berichtskonfigurationsdatei nicht im Modulpfad '{0}' gefunden. +'@ diff --git a/AsBuiltReport.Core/Language/el-GR/AsBuiltReportCoreStyle.psd1 b/AsBuiltReport.Core/Language/el-GR/AsBuiltReportCoreStyle.psd1 new file mode 100644 index 0000000..ff48ac8 --- /dev/null +++ b/AsBuiltReport.Core/Language/el-GR/AsBuiltReportCoreStyle.psd1 @@ -0,0 +1,11 @@ +# culture = 'el-GR' +ConvertFrom-StringData @' + Footer = Σελίδα + Logo = Λογότυπο AsBuiltReport + CoverPageWarning = Δεν είναι δυνατή η εμφάνιση της εικόνας της σελίδας εξωφύλλου. Ορίστε το 'ShowCoverPageImage' σε 'false' στο αρχείο διαμόρφωσης JSON της αναφοράς για να αποφύγετε αυτό το σφάλμα. + CoverPage = Σελίδα Εξωφύλλου + Author = Συγγραφέας: + Date = Ημερομηνία: + Version = Έκδοση: + TOC = Πίνακας Περιεχομένων +'@ diff --git a/AsBuiltReport.Core/Language/el-GR/New-AsBuiltConfig.psd1 b/AsBuiltReport.Core/Language/el-GR/New-AsBuiltConfig.psd1 new file mode 100644 index 0000000..d8856cb --- /dev/null +++ b/AsBuiltReport.Core/Language/el-GR/New-AsBuiltConfig.psd1 @@ -0,0 +1,58 @@ +# culture = 'el-GR' +@{ + +# As Built Report Information +ReportInfo = ConvertFrom-StringData @' + BannerTitle = Πληροφορίες As Built Report + ReportAuthor = Εισάγετε το όνομα του συγγραφέα για αυτό το As Built Report [{0}] +'@ + +# Company Configuration +CompanyConfig = ConvertFrom-StringData @' + BannerTitle = Πληροφορίες Εταιρείας + CompanyInfo = Θέλετε να εισάγετε πληροφορίες εταιρείας για το As Built Report; (y/N) + CompanyFullName = Εισάγετε το Πλήρες Όνομα της Εταιρείας + CompanyShortName = Εισάγετε το Σύντομο Όνομα της Εταιρείας + CompanyContact = Εισάγετε το Στοιχείο Επικοινωνίας της Εταιρείας + CompanyEmail = Εισάγετε τη Διεύθυνση Email της Εταιρείας + CompanyPhone = Εισάγετε τον Αριθμό Τηλεφώνου της Εταιρείας + CompanyAddress = Εισάγετε τη Διεύθυνση της Εταιρείας +'@ + +# Email Configuration +EmailConfig = ConvertFrom-StringData @' + BannerTitle = Διαμόρφωση Email + ConfigureMailSettings = Θέλετε να εισάγετε τη διαμόρφωση SMTP; (y/N) + MailServer = Εισάγετε το FQDN / τη διεύθυνση IP του διακομιστή αλληλογραφίας + EmptyMailServerAddress = Η διεύθυνση του διακομιστή αλληλογραφίας δεν μπορεί να είναι κενή. Εισάγετε ένα έγκυρο FQDN / διεύθυνση IP διακομιστή αλληλογραφίας. + InvalidMailServer = Το '{0}' δεν είναι έγκυρο FQDN ή διεύθυνση IP. Εισάγετε ένα έγκυρο FQDN / διεύθυνση IP διακομιστή αλληλογραφίας. + MailServerPort587 = Εισάγετε τον αριθμό θύρας του διακομιστή αλληλογραφίας [587] + InvalidMailServerPort587 = Μη έγκυρος αριθμός θύρας. Εισάγετε έναν αριθμό μεταξύ 1 και 65535 ή πατήστε Enter για την προεπιλογή [587]. + MailServerPort25 = Εισάγετε τον αριθμό θύρας του διακομιστή αλληλογραφίας [25] + InvalidMailServerPort25 = Μη έγκυρος αριθμός θύρας. Εισάγετε έναν αριθμό μεταξύ 1 και 65535 ή πατήστε Enter για την προεπιλογή [25]. + MailServerUseSSL = Χρήση SSL για τη σύνδεση με τον διακομιστή αλληλογραφίας; (y/N) + MailCredentials = Απαιτείται έλεγχος ταυτότητας διακομιστή αλληλογραφίας; (y/N) + MailFrom = Εισάγετε τη διεύθυνση email του αποστολέα + MailTo = Εισάγετε τη διεύθυνση email του παραλήπτη + EmptyEmail = Η διεύθυνση email δεν μπορεί να είναι κενή. Εισάγετε μια έγκυρη διεύθυνση email. + InvalidEmail = Το '{0}' δεν είναι έγκυρη διεύθυνση email. Εισάγετε μια έγκυρη διεύθυνση email. + AnotherRecipient = Θέλετε να εισάγετε άλλον παραλήπτη; (y/N) + MailBodyPrompt = Εισάγετε το περιεχόμενο του σώματος του μηνύματος email + MailBody = As Built Report επισυνάπτεται +'@ + +# Report Configuration +ReportConfig = ConvertFrom-StringData @' + BannerTitle = Διαμόρφωση As Built Report + ReportConfigFolder = Εισάγετε την πλήρη διαδρομή του φακέλου που θα χρησιμοποιηθεί για την αποθήκευση αρχείων διαμόρφωσης λειτουργικής μονάδας αναφορών και προσαρμοσμένων σεναρίων στυλ [{0}] + OverwriteReportConfig = Υπάρχει ήδη ένα αρχείο διαμόρφωσης λειτουργικής μονάδας αναφοράς για {0} στον καθορισμένο φάκελο. Θέλετε να το αντικαταστήσετε; (y/N) + CopyFile = Αντιγραφή του '{0}' στο '{1}'. + OverwriteFile = Αντιγραφή του '{0}' στο '{1}'. Αντικατάσταση υπάρχοντος αρχείου. + SaveAsBuiltConfig = Θέλετε να αποθηκεύσετε το αρχείο διαμόρφωσης της κύριας λειτουργικής μονάδας As Built Report; (Y/n) + AsBuiltName = Εισάγετε ένα όνομα για το αρχείο διαμόρφωσης As Built Report [AsBuiltReport] + AsBuiltExportPath = Εισάγετε τη διαδρομή για την αποθήκευση του αρχείου διαμόρφωσης As Built Report [{0}] + ConfigFolder = Δημιουργία φακέλου διαμόρφωσης As Built Report '{0}'. + SaveConfig = Αποθήκευση αρχείου διαμόρφωσης As Built Report '{0}.json' στη διαδρομή '{1}'. + NotSaved = Το αρχείο διαμόρφωσης As Built Report δεν αποθηκεύτηκε. +'@ +} diff --git a/AsBuiltReport.Core/Language/el-GR/New-AsBuiltReport.psd1 b/AsBuiltReport.Core/Language/el-GR/New-AsBuiltReport.psd1 new file mode 100644 index 0000000..f031e5e --- /dev/null +++ b/AsBuiltReport.Core/Language/el-GR/New-AsBuiltReport.psd1 @@ -0,0 +1,40 @@ +# culture = 'el-GR' +ConvertFrom-StringData @' + PwshISE = Το AsBuiltReport δεν μπορεί να εκτελεστεί από το Windows PowerShell ISE. Χρησιμοποιήστε ένα παράθυρο εντολών PowerShell. + Password = Κωδικός πρόσβασης για τον χρήστη {0} + OutputFolderPath = Το OutputFolderPath '{0}' δεν είναι έγκυρη διαδρομή φακέλου. + LoadConfig = Φόρτωση διαμόρφωσης As Built Report από {0}. + NoConfigFound = Δεν βρέθηκε διαμόρφωση As Built Report στη διαδρομή '{0}'. + GeneratingReport = Δημιουργία νέας διαμόρφωσης As Built Report. + StyleScriptNotFound = Δεν βρέθηκε σενάριο στυλ αναφοράς στη διαδρομή '{0}'. + ReportModuleNotFound = Δεν βρέθηκε αρχείο διαμόρφωσης αναφοράς {0} στη διαδρομή '{1}'. + LoadingReportConfig = Φόρτωση αρχείου διαμόρφωσης αναφοράς {0} από τη διαδρομή '{1}'. + ReportConfigNotFound = Η διαμόρφωση αναφοράς δεν βρέθηκε στη διαδρομή μονάδας '{0}'. + SetReportFileName = Ορισμός ονόματος αρχείου αναφοράς σε '{0}'. + EmailBannerTitle = Διαπιστευτήρια Διακομιστή Email + EmailCredentials = Εισαγάγετε διαπιστευτήρια για {0}. + InstalledModule = Το AsBuiltReport.Core {0} είναι εγκατεστημένο αυτήν τη στιγμή. + AvailableModule = Το AsBuiltReport.Core {0} είναι διαθέσιμο. + UpdateModule = Εκτελέστε 'Update-Module -Name AsBuiltReport.Core -Force' για εγκατάσταση της πιο πρόσφατης έκδοσης. + ReportGenerating = Περιμένετε ενώ δημιουργείται η αναφορά {0} As Built. + ReportInitializing = > Αρχικοποίηση πλαισίου αναφοράς... + DocumentStyle = > Φόρτωση στυλ εγγράφου... + TargetSystem = > Σύνδεση με το σύστημα προορισμού και συλλογή δεδομένων... + ExecutionFailed = Η εκτέλεση της μονάδας αναφοράς απέτυχε: {0} + BuildingDocument = > Δημιουργία δομής εγγράφου... + ExportingDocument = > Εξαγωγή εγγράφου... + Failed = [ΑΠΟΤΥΧΙΑ] Η δημιουργία αναφοράς απέτυχε + ReportStyleScript = Εκτέλεση σεναρίου στυλ αναφοράς από τη διαδρομή '{0}'. + InteractiveAuth = Ο διαδραστικός έλεγχος ταυτότητας είναι ενεργοποιημένος. Ελέγξτε τα παράθυρα ελέγχου ταυτότητας για να πραγματοποιήσετε έλεγχο ταυτότητας στο σύστημα προορισμού σας. + OutputFolder = {0} As Built Report '{1}' αποθηκεύτηκε στο '{2}'. + ReportModuleInfo1 = Τεκμηρίωση: https://github.com/AsBuiltReport/AsBuiltReport.{0} + ReportModuleInfo2 = Ζητήματα ή αναφορά σφαλμάτων: https://github.com/AsBuiltReport/AsBuiltReport.{0}/issues + ReportModuleInfo3 = Μην ξεχάσετε να ενημερώσετε το αρχείο διαμόρφωσης αναφοράς σας μετά από κάθε νέα έκδοση: https://www.asbuiltreport.com/user-guide/new-asbuiltreportconfig/ + ProjectWebsite = Ανατρέξτε στον ιστότοπο του έργου AsBuiltReport για πιο λεπτομερείς πληροφορίες: https://www.asbuiltreport.com + CommunityProject = Το AsBuiltReport είναι ένα έργο ανοιχτού κώδικα που διατηρείται από την κοινότητα. Δεν έχει χορηγία, υποστήριξη ή σύνδεση με οποιουσδήποτε προμηθευτές τεχνολογίας, τους υπαλλήλους τους ή τις συνδεδεμένες εταιρείες τους. + ReportModuleInstalled = Το {0} {1} είναι εγκατεστημένο αυτήν τη στιγμή. + ReportModuleAvailable = Το {0} {1} είναι διαθέσιμο. + ReportModuleUpdate = Εκτελέστε 'Update-Module -Name {0} -Force' για εγκατάσταση της πιο πρόσφατης έκδοσης. + RequiredModuleNotInstalled = Απαιτείται {0} {1} ή νεότερη έκδοση. Εκτελέστε 'Install-Module -Name {0} -RequiredVersion {1} -AllowClobber' για εγκατάσταση της απαιτούμενης μονάδας. + RequiredModuleTooOld = Το {0} {1} είναι εγκατεστημένο αυτήν τη στιγμή. Απαιτείται {0} {2} ή νεότερη έκδοση. Εκτελέστε 'Update-Module -Name {0} -RequiredVersion {2} -Force' για ενημέρωση στην απαιτούμενη έκδοση. +'@ diff --git a/AsBuiltReport.Core/Language/el-GR/New-AsBuiltReportConfig.psd1 b/AsBuiltReport.Core/Language/el-GR/New-AsBuiltReportConfig.psd1 new file mode 100644 index 0000000..52f71b7 --- /dev/null +++ b/AsBuiltReport.Core/Language/el-GR/New-AsBuiltReportConfig.psd1 @@ -0,0 +1,11 @@ +# culture = 'el-GR' +ConvertFrom-StringData @' + FolderNotExist = Ο φάκελος '{0}' δεν υπάρχει. Δημιουργήστε τον φάκελο και εκτελέστε ξανά το New-AsBuiltReportConfig. + ProcessConfig = Επεξεργασία αρχείου διαμόρφωσης αναφοράς {0} από τη λειτουργική μονάδα {1}, έκδοση {2}. + CopyConfig = Αντιγραφή αρχείου διαμόρφωσης αναφοράς '{0}' στο '{1}'. + CopyModuleConfig = Αντιγραφή αρχείου διαμόρφωσης αναφοράς {0} '{1}' στο '{2}'. + CreateConfig = Το αρχείο διαμόρφωσης αναφοράς {0} '{1}.json' δημιουργήθηκε στο '{2}'. + OverWriteConfig = Αντιγραφή αρχείου διαμόρφωσης αναφοράς '{0}' στο '{1}'. Αντικατάσταση υπάρχοντος αρχείου. + ForceOverwrite = Το αρχείο διαμόρφωσης αναφοράς {0} '{1}.json' υπάρχει ήδη στο '{2}'. Χρησιμοποιήστε '-Force' για να αντικαταστήσετε το υπάρχον αρχείο. + ConfigNotFound = Το αρχείο διαμόρφωσης αναφοράς δεν βρέθηκε στη διαδρομή λειτουργικής μονάδας '{0}'. +'@ diff --git a/AsBuiltReport.Core/Language/en-GB/AsBuiltReportCoreStyle.psd1 b/AsBuiltReport.Core/Language/en-GB/AsBuiltReportCoreStyle.psd1 new file mode 100644 index 0000000..ce3e4e8 --- /dev/null +++ b/AsBuiltReport.Core/Language/en-GB/AsBuiltReportCoreStyle.psd1 @@ -0,0 +1,11 @@ +# culture = 'en-US' +ConvertFrom-StringData @' + Footer = Page + Logo = AsBuiltReport Logo + CoverPageWarning = Unable to display cover page image. Please set 'ShowCoverPageImage' to 'false' in the report JSON configuration file to avoid this error. + CoverPage = Cover Page + Author = Author: + Date = Date: + Version = Version: + TOC = Table of Contents +'@ \ No newline at end of file diff --git a/AsBuiltReport.Core/Language/en-GB/New-AsBuiltConfig.psd1 b/AsBuiltReport.Core/Language/en-GB/New-AsBuiltConfig.psd1 new file mode 100644 index 0000000..c07e59b --- /dev/null +++ b/AsBuiltReport.Core/Language/en-GB/New-AsBuiltConfig.psd1 @@ -0,0 +1,58 @@ +# culture = 'en-US' +@{ + +# As Built Report Information +ReportInfo = ConvertFrom-StringData @' + BannerTitle = As Built Report Information + ReportAuthor = Enter the name of the author for this As Built Report [{0}] +'@ + +# Company Configuration +CompanyConfig = ConvertFrom-StringData @' + BannerTitle = Company Information + CompanyInfo = Would you like to enter company information for the As Built Report? (y/N) + CompanyFullName = Enter the Full Company Name + CompanyShortName = Enter the Company Short Name + CompanyContact = Enter the Company Contact + CompanyEmail = Enter the Company Email Address + CompanyPhone = Enter the Company Phone Number + CompanyAddress = Enter the Company Address +'@ + +# Email Configuration +EmailConfig = ConvertFrom-StringData @' + BannerTitle = Email Configuration + ConfigureMailSettings = Would you like to enter SMTP configuration? (y/N) + MailServer = Enter the mail server FQDN / IP address + EmptyMailServerAddress = Mail server address cannot be empty. Please enter a valid mail server FQDN / IP address. + InvalidMailServer = '{0}' is not a valid FQDN or IP address. Please enter a valid mail server FQDN / IP address. + MailServerPort587 = Enter the mail server port number [587] + InvalidMailServerPort587 = Invalid port number. Please enter a number between 1 and 65535, or press Enter for default [587]. + MailServerPort25 = Enter the mail server port number [25] + InvalidMailServerPort25 = Invalid port number. Please enter a number between 1 and 65535, or press Enter for default [25]. + MailServerUseSSL = Use SSL for mail server connection? (y/N) + MailCredentials = Require mail server authentication? (y/N) + MailFrom = Enter the mail sender email address + MailTo = Enter the mail server recipient email address + EmptyEmail = Email address cannot be empty. Please enter a valid email address. + InvalidEmail = '{0}' is not a valid email address. Please enter a valid email address. + AnotherRecipient = Do you want to enter another recipient? (y/N) + MailBodyPrompt = Enter the email message body content + MailBody = As Built Report attached +'@ + +# Report Configuration +ReportConfig = ConvertFrom-StringData @' + BannerTitle = As Built Report Configuration + ReportConfigFolder = Enter the full path of the folder to use for storing report module configuration files and custom style scripts [{0}] + OverwriteReportConfig = A report module configuration file for {0} already exists in the specified folder. Would you like to overwrite it? (y/N) + CopyFile = Copying '{0}' to '{1}'. + OverwriteFile = Copying '{0}' to '{1}'. Overwriting existing file. + SaveAsBuiltConfig = Would you like to save the As Built Report core module configuration file? (Y/n) + AsBuiltName = Enter a name for the As Built Report configuration file [AsBuiltReport] + AsBuiltExportPath = Enter the path to save the As Built Report configuration file [{0}] + ConfigFolder = Creating As Built Report configuration folder '{0}'. + SaveConfig = Saving As Built Report configuration file '{0}.json' to path '{1}'. + NotSaved = As Built Report configuration file not saved. +'@ +} \ No newline at end of file diff --git a/AsBuiltReport.Core/Language/en-GB/New-AsBuiltReport.psd1 b/AsBuiltReport.Core/Language/en-GB/New-AsBuiltReport.psd1 new file mode 100644 index 0000000..e5ed349 --- /dev/null +++ b/AsBuiltReport.Core/Language/en-GB/New-AsBuiltReport.psd1 @@ -0,0 +1,40 @@ +# culture = 'en-GB' +ConvertFrom-StringData @' + PwshISE = AsBuiltReport cannot be run from Windows PowerShell ISE. Please use a PowerShell command window instead. + Password = Password for user {0} + OutputFolderPath = OutputFolderPath '{0}' is not a valid folder path. + LoadConfig = Loading As Built Report configuration from {0}. + NoConfigFound = Could not find As Built Report configuration in path '{0}'. + GeneratingReport = Generating new As Built Report configuration. + StyleScriptNotFound = Could not find report style script in path '{0}'. + ReportModuleNotFound = Could not find {0} report configuration file in path '{1}'. + LoadingReportConfig = Loading {0} report configuration file from path '{1}'. + ReportConfigNotFound = Report configuration not found in module path '{0}'. + SetReportFileName = Setting report file name to '{0}'. + EmailBannerTitle = Email Server Credentials + EmailCredentials = Please enter credentials for {0}. + InstalledModule = AsBuiltReport.Core {0} is currently installed. + AvailableModule = AsBuiltReport.Core {0} is available. + UpdateModule = Run 'Update-Module -Name AsBuiltReport.Core -Force' to install the latest version. + ReportGenerating = Please wait while the {0} As Built Report is being generated. + ReportInitializing = > Initializing report framework... + DocumentStyle = > Loading document style... + TargetSystem = > Connecting to target system and gathering data... + ExecutionFailed = Report module execution failed: {0} + BuildingDocument = > Building document structure... + ExportingDocument = > Exporting document... + Failed = [FAILED] Report generation failed + ReportStyleScript = Executing report style script from path '{0}'. + InteractiveAuth = Interactive authentication is enabled. Please check for authentication windows to authenticate to your target system. + OutputFolder = {0} As Built Report '{1}' has been saved to '{2}'. + ReportModuleInfo1 = Documentation: https://github.com/AsBuiltReport/AsBuiltReport.{0} + ReportModuleInfo2 = Issues or bug reporting: https://github.com/AsBuiltReport/AsBuiltReport.{0}/issues + ReportModuleInfo3 = Do not forget to update your report configuration file after each new version release: https://www.asbuiltreport.com/user-guide/new-asbuiltreportconfig/ + ProjectWebsite = Please refer to the AsBuiltReport project website for more detailed information: https://www.asbuiltreport.com + CommunityProject = AsBuiltReport is a community-maintained open source project. It has no sponsorship, endorsement, or affiliation with any technology vendors, their employees, or affiliates. + ReportModuleInstalled = {0} {1} is currently installed. + ReportModuleAvailable = {0} {1} is available. + ReportModuleUpdate = Run 'Update-Module -Name {0} -Force' to install the latest version. + RequiredModuleNotInstalled = {0} {1} or higher is required. Run 'Install-Module -Name {0} -RequiredVersion {1} -AllowClobber' to install the required module. + RequiredModuleTooOld = {0} {1} is currently installed. {0} {2} or higher is required. Run 'Update-Module -Name {0} -RequiredVersion {2} -Force' to update to the required version. +'@ \ No newline at end of file diff --git a/AsBuiltReport.Core/Language/en-GB/New-AsBuiltReportConfig.psd1 b/AsBuiltReport.Core/Language/en-GB/New-AsBuiltReportConfig.psd1 new file mode 100644 index 0000000..f3260f2 --- /dev/null +++ b/AsBuiltReport.Core/Language/en-GB/New-AsBuiltReportConfig.psd1 @@ -0,0 +1,11 @@ +# culture = 'en-US' +ConvertFrom-StringData @' + FolderNotExist = The folder '{0}' does not exist. Please create the folder and run New-AsBuiltReportConfig again. + ProcessConfig = Processing {0} report configuration file from module {1}, version {2}. + CopyConfig = Copying report configuration file '{0}' to '{1}'. + CopyModuleConfig = Copying {0} report configuration file '{1}' to '{2}'. + CreateConfig = {0} report configuration file '{1}.json' created in '{2}'. + OverWriteConfig = Copying report configuration file '{0})' to '{1}'. Overwriting existing file. + ForceOverwrite = {0} report configuration file '{1}.json' already exists in '{2}'. Use '-Force' to overwrite existing file. + ConfigNotFound = Report configuration file not found in module path '{0}'. +'@ \ No newline at end of file diff --git a/AsBuiltReport.Core/Language/en-US/AsBuiltReportCoreStyle.psd1 b/AsBuiltReport.Core/Language/en-US/AsBuiltReportCoreStyle.psd1 new file mode 100644 index 0000000..ce3e4e8 --- /dev/null +++ b/AsBuiltReport.Core/Language/en-US/AsBuiltReportCoreStyle.psd1 @@ -0,0 +1,11 @@ +# culture = 'en-US' +ConvertFrom-StringData @' + Footer = Page + Logo = AsBuiltReport Logo + CoverPageWarning = Unable to display cover page image. Please set 'ShowCoverPageImage' to 'false' in the report JSON configuration file to avoid this error. + CoverPage = Cover Page + Author = Author: + Date = Date: + Version = Version: + TOC = Table of Contents +'@ \ No newline at end of file diff --git a/AsBuiltReport.Core/Language/en-US/New-AsBuiltConfig.psd1 b/AsBuiltReport.Core/Language/en-US/New-AsBuiltConfig.psd1 new file mode 100644 index 0000000..c07e59b --- /dev/null +++ b/AsBuiltReport.Core/Language/en-US/New-AsBuiltConfig.psd1 @@ -0,0 +1,58 @@ +# culture = 'en-US' +@{ + +# As Built Report Information +ReportInfo = ConvertFrom-StringData @' + BannerTitle = As Built Report Information + ReportAuthor = Enter the name of the author for this As Built Report [{0}] +'@ + +# Company Configuration +CompanyConfig = ConvertFrom-StringData @' + BannerTitle = Company Information + CompanyInfo = Would you like to enter company information for the As Built Report? (y/N) + CompanyFullName = Enter the Full Company Name + CompanyShortName = Enter the Company Short Name + CompanyContact = Enter the Company Contact + CompanyEmail = Enter the Company Email Address + CompanyPhone = Enter the Company Phone Number + CompanyAddress = Enter the Company Address +'@ + +# Email Configuration +EmailConfig = ConvertFrom-StringData @' + BannerTitle = Email Configuration + ConfigureMailSettings = Would you like to enter SMTP configuration? (y/N) + MailServer = Enter the mail server FQDN / IP address + EmptyMailServerAddress = Mail server address cannot be empty. Please enter a valid mail server FQDN / IP address. + InvalidMailServer = '{0}' is not a valid FQDN or IP address. Please enter a valid mail server FQDN / IP address. + MailServerPort587 = Enter the mail server port number [587] + InvalidMailServerPort587 = Invalid port number. Please enter a number between 1 and 65535, or press Enter for default [587]. + MailServerPort25 = Enter the mail server port number [25] + InvalidMailServerPort25 = Invalid port number. Please enter a number between 1 and 65535, or press Enter for default [25]. + MailServerUseSSL = Use SSL for mail server connection? (y/N) + MailCredentials = Require mail server authentication? (y/N) + MailFrom = Enter the mail sender email address + MailTo = Enter the mail server recipient email address + EmptyEmail = Email address cannot be empty. Please enter a valid email address. + InvalidEmail = '{0}' is not a valid email address. Please enter a valid email address. + AnotherRecipient = Do you want to enter another recipient? (y/N) + MailBodyPrompt = Enter the email message body content + MailBody = As Built Report attached +'@ + +# Report Configuration +ReportConfig = ConvertFrom-StringData @' + BannerTitle = As Built Report Configuration + ReportConfigFolder = Enter the full path of the folder to use for storing report module configuration files and custom style scripts [{0}] + OverwriteReportConfig = A report module configuration file for {0} already exists in the specified folder. Would you like to overwrite it? (y/N) + CopyFile = Copying '{0}' to '{1}'. + OverwriteFile = Copying '{0}' to '{1}'. Overwriting existing file. + SaveAsBuiltConfig = Would you like to save the As Built Report core module configuration file? (Y/n) + AsBuiltName = Enter a name for the As Built Report configuration file [AsBuiltReport] + AsBuiltExportPath = Enter the path to save the As Built Report configuration file [{0}] + ConfigFolder = Creating As Built Report configuration folder '{0}'. + SaveConfig = Saving As Built Report configuration file '{0}.json' to path '{1}'. + NotSaved = As Built Report configuration file not saved. +'@ +} \ No newline at end of file diff --git a/AsBuiltReport.Core/Language/en-US/New-AsBuiltReport.psd1 b/AsBuiltReport.Core/Language/en-US/New-AsBuiltReport.psd1 new file mode 100644 index 0000000..f95f04a --- /dev/null +++ b/AsBuiltReport.Core/Language/en-US/New-AsBuiltReport.psd1 @@ -0,0 +1,40 @@ +# culture = 'en-US' +ConvertFrom-StringData @' + PwshISE = AsBuiltReport cannot be run from Windows PowerShell ISE. Please use a PowerShell command window instead. + Password = Password for user {0} + OutputFolderPath = OutputFolderPath '{0}' is not a valid folder path. + LoadConfig = Loading As Built Report configuration from {0}. + NoConfigFound = Could not find As Built Report configuration in path '{0}'. + GeneratingReport = Generating new As Built Report configuration. + StyleScriptNotFound = Could not find report style script in path '{0}'. + ReportModuleNotFound = Could not find {0} report configuration file in path '{1}'. + LoadingReportConfig = Loading {0} report configuration file from path '{1}'. + ReportConfigNotFound = Report configuration not found in module path '{0}'. + SetReportFileName = Setting report file name to '{0}'. + EmailBannerTitle = Email Server Credentials + EmailCredentials = Please enter credentials for {0}. + InstalledModule = AsBuiltReport.Core {0} is currently installed. + AvailableModule = AsBuiltReport.Core {0} is available. + UpdateModule = Run 'Update-Module -Name AsBuiltReport.Core -Force' to install the latest version. + ReportGenerating = Please wait while the {0} As Built Report is being generated. + ReportInitializing = > Initializing report framework... + DocumentStyle = > Loading document style... + TargetSystem = > Connecting to target system and gathering data... + ExecutionFailed = Report module execution failed: {0} + BuildingDocument = > Building document structure... + ExportingDocument = > Exporting document... + Failed = [FAILED] Report generation failed + ReportStyleScript = Executing report style script from path '{0}'. + InteractiveAuth = Interactive authentication is enabled. Please check for authentication windows to authenticate to your target system. + OutputFolder = {0} As Built Report '{1}' has been saved to '{2}'. + ReportModuleInfo1 = Documentation: https://github.com/AsBuiltReport/AsBuiltReport.{0} + ReportModuleInfo2 = Issues or bug reporting: https://github.com/AsBuiltReport/AsBuiltReport.{0}/issues + ReportModuleInfo3 = Do not forget to update your report configuration file after each new version release: https://www.asbuiltreport.com/user-guide/new-asbuiltreportconfig/ + ProjectWebsite = Please refer to the AsBuiltReport project website for more detailed information: https://www.asbuiltreport.com + CommunityProject = AsBuiltReport is a community-maintained open source project. It has no sponsorship, endorsement, or affiliation with any technology vendors, their employees, or affiliates. + ReportModuleInstalled = {0} {1} is currently installed. + ReportModuleAvailable = {0} {1} is available. + ReportModuleUpdate = Run 'Update-Module -Name {0} -Force' to install the latest version. + RequiredModuleNotInstalled = {0} {1} or higher is required. Run 'Install-Module -Name {0} -RequiredVersion {1} -AllowClobber' to install the required module. + RequiredModuleTooOld = {0} {1} is currently installed. {0} {2} or higher is required. Run 'Update-Module -Name {0} -RequiredVersion {2} -Force' to update to the required version. +'@ \ No newline at end of file diff --git a/AsBuiltReport.Core/Language/en-US/New-AsBuiltReportConfig.psd1 b/AsBuiltReport.Core/Language/en-US/New-AsBuiltReportConfig.psd1 new file mode 100644 index 0000000..f3260f2 --- /dev/null +++ b/AsBuiltReport.Core/Language/en-US/New-AsBuiltReportConfig.psd1 @@ -0,0 +1,11 @@ +# culture = 'en-US' +ConvertFrom-StringData @' + FolderNotExist = The folder '{0}' does not exist. Please create the folder and run New-AsBuiltReportConfig again. + ProcessConfig = Processing {0} report configuration file from module {1}, version {2}. + CopyConfig = Copying report configuration file '{0}' to '{1}'. + CopyModuleConfig = Copying {0} report configuration file '{1}' to '{2}'. + CreateConfig = {0} report configuration file '{1}.json' created in '{2}'. + OverWriteConfig = Copying report configuration file '{0})' to '{1}'. Overwriting existing file. + ForceOverwrite = {0} report configuration file '{1}.json' already exists in '{2}'. Use '-Force' to overwrite existing file. + ConfigNotFound = Report configuration file not found in module path '{0}'. +'@ \ No newline at end of file diff --git a/AsBuiltReport.Core/Language/es-ES/AsBuiltReportCoreStyle.psd1 b/AsBuiltReport.Core/Language/es-ES/AsBuiltReportCoreStyle.psd1 new file mode 100644 index 0000000..f502134 --- /dev/null +++ b/AsBuiltReport.Core/Language/es-ES/AsBuiltReportCoreStyle.psd1 @@ -0,0 +1,11 @@ +# culture = 'es-ES' +ConvertFrom-StringData @' + Footer = Página + Logo = AsBuiltReport Logo + CoverPageWarning = No se puede mostrar la imagen de portada. Configure "ShowCoverPageImage" como "false" en el archivo de configuración JSON del informe para evitar este error. + CoverPage = Portada + Author = Autor: + Date = Fecha: + Version = Versión: + TOC = Tabla de Contenido +'@ \ No newline at end of file diff --git a/AsBuiltReport.Core/Language/es-ES/New-AsBuiltConfig.psd1 b/AsBuiltReport.Core/Language/es-ES/New-AsBuiltConfig.psd1 new file mode 100644 index 0000000..6b13bfb --- /dev/null +++ b/AsBuiltReport.Core/Language/es-ES/New-AsBuiltConfig.psd1 @@ -0,0 +1,58 @@ +# culture = 'es-ES' +@{ + +# Información del Informe As Built +ReportInfo = ConvertFrom-StringData @' + BannerTitle = Información del Informe As Built + ReportAuthor = Ingrese el nombre del autor para este Informe As Built [{0}] +'@ + +# Configuración de la Empresa +CompanyConfig = ConvertFrom-StringData @' + BannerTitle = Información de la Empresa + CompanyInfo = ¿Desea ingresar información de la empresa para el Informe Según Construcción? (y/N) + CompanyFullName = Ingrese el Nombre Completo de la Empresa + CompanyShortName = Ingrese el Nombre Corto de la Empresa + CompanyContact = Ingrese el Contacto de la Empresa + CompanyEmail = Ingrese la Dirección de Correo Electrónico de la Empresa + CompanyPhone = Ingrese el Número de Teléfono de la Empresa + CompanyAddress = Ingrese la Dirección de la Empresa +'@ + +# Configuración de Correo Electrónico +EmailConfig = ConvertFrom-StringData @' + BannerTitle = Configuración de Correo Electrónico + ConfigureMailSettings = ¿Le gustaría ingresar la configuración SMTP? (y/N) + MailServer = Ingrese el FQDN / dirección IP del servidor de correo + EmptyMailServerAddress = La dirección del servidor de correo no puede estar vacía. Por favor ingrese un FQDN / dirección IP válida del servidor de correo. + InvalidMailServer = '{0}' no es un FQDN o dirección IP válida. Por favor ingrese un FQDN / dirección IP válida del servidor de correo. + MailServerPort587 = Ingrese el número de puerto del servidor de correo [587] + InvalidMailServerPort587 = Número de puerto inválido. Por favor ingrese un número entre 1 y 65535, o presione Enter para el valor predeterminado [587]. + MailServerPort25 = Ingrese el número de puerto del servidor de correo [25] + InvalidMailServerPort25 = Número de puerto inválido. Por favor ingrese un número entre 1 y 65535, o presione Enter para el valor predeterminado [25]. + MailServerUseSSL = ¿Se requiere autenticación del servidor de correo? (y/N) + MailCredentials = ¿Requiere autenticación del servidor de correo? (y/N) + MailFrom = Ingrese la dirección de correo electrónico del remitente + MailTo = Introduzca la dirección de correo electrónico del destinatario del servidor de correo + EmptyEmail = La dirección de correo electrónico no puede estar vacía. Por favor ingrese una dirección de correo electrónico válida. + InvalidEmail = '{0}' no es una dirección de correo electrónico válida. Por favor ingrese una dirección de correo electrónico válida. + AnotherRecipient = ¿Quieres introducir otro destinatario? (y/N) + MailBodyPrompt = Ingrese el contenido del cuerpo del mensaje de correo electrónico + MailBody = Informe As Built adjunto +'@ + +# Configuración del Informe +ReportConfig = ConvertFrom-StringData @' + BannerTitle = Configuración del Informe Según Construcción + ReportConfigFolder = Ingrese la ruta completa de la carpeta a usar para almacenar archivos de configuración del módulo de informe y scripts de estilo personalizados [{0}] + OverwriteReportConfig = Ya existe un archivo de configuración del módulo de informe para {0} en la carpeta especificada. ¿Le gustaría sobrescribirlo? (y/N) + CopyFile = Copiando '{0}' a '{1}'. + OverwriteFile = Copiando '{0}' a '{1}'. Sobrescribiendo archivo existente. + SaveAsBuiltConfig = ¿Le gustaría guardar el archivo de configuración del módulo principal del Informe As Built? (Y/n) + AsBuiltName = Ingrese un nombre para el archivo de configuración del Informe As Built [AsBuiltReport] + AsBuiltExportPath = Ingrese la ruta para guardar el archivo de configuración del Informe As Built [{0}] + ConfigFolder = Creando carpeta de configuración del Informe As Built '{0}'. + SaveConfig = Guardando archivo de configuración del Informe As Built '{0}.json' en la ruta '{1}'. + NotSaved = Archivo de configuración del Informe As Built no guardado. +'@ +} \ No newline at end of file diff --git a/AsBuiltReport.Core/Language/es-ES/New-AsBuiltReport.psd1 b/AsBuiltReport.Core/Language/es-ES/New-AsBuiltReport.psd1 new file mode 100644 index 0000000..c400b3f --- /dev/null +++ b/AsBuiltReport.Core/Language/es-ES/New-AsBuiltReport.psd1 @@ -0,0 +1,40 @@ +# culture = 'es-ES' +ConvertFrom-StringData @' + PwshISE = AsBuiltReport no se puede ejecutar desde Windows PowerShell ISE. Utilice una ventana de comandos de PowerShell. + Password = Contraseña para usuario {0} + OutputFolderPath = OutputFolderPath '{0}' no es una ruta de carpeta válida. + LoadConfig = Cargando configuración de informe según construcción desde {0}. + NoConfigFound = No se pudo encontrar la configuración del Informe tal como fue construido en la ruta '{0}'. + GeneratingReport = Generando nueva configuración de Informe As Built. + StyleScriptNotFound = No se pudo encontrar el script de estilo de informe en la ruta '{0}'. + ReportModuleNotFound = No se pudo encontrar el archivo de configuración del informe {0} en la ruta '{1}'. + LoadingReportConfig = Cargando archivo de configuración de informe {0} desde la ruta '{1}'. + ReportConfigNotFound = Configuración del informe no encontrada en la ruta del módulo '{0}'. + SetReportFileName = Establecer el nombre del archivo de informe a '{0}'. + EmailBannerTitle = Credenciales del servidor de correo electrónico + EmailCredentials = Ingrese las credenciales para {0}. + InstalledModule = AsBuiltReport.Core {0} está actualmente instalado. + AvailableModule = AsBuiltReport.Core {0} está disponible. + UpdateModule = Correr 'Update-Module -Name AsBuiltReport.Core -Force' para instalar la última versión. + ReportGenerating = Espere mientras se genera el informe As Built {0}. + ReportInitializing = > Inicializando marco de informe... + DocumentStyle = > Cargando estilo de documento... + TargetSystem = > Conectando al sistema de destino y recopilando datos... + ExecutionFailed = Error en la ejecución del módulo de informe: {0} + BuildingDocument = > Construyendo estructura de documento... + ExportingDocument = > Exportando documento... + Failed = [ERROR] Falló la generación del informe + ReportStyleScript = Ejecutando script de estilo de informe desde la ruta '{0}'. + InteractiveAuth = La autenticación interactiva está habilitada. Por favor, verifique las ventanas de autenticación para autenticarse en su sistema de destino. + OutputFolder = {0} As Built Report '{1}' se ha guardado en '{2}'. + ReportModuleInfo1 = Documentación: https://github.com/AsBuiltReport/AsBuiltReport.{0} + ReportModuleInfo2 = Problemas o informes de errores: https://github.com/AsBuiltReport/AsBuiltReport.{0}/issues + ReportModuleInfo3 = No olvide actualizar su archivo de configuración de informe después de cada nueva versión: https://www.asbuiltreport.com/user-guide/new-asbuiltreportconfig/ + ProjectWebsite = Consulte el sitio web del proyecto AsBuiltReport para obtener información más detallada: https://www.asbuiltreport.com + CommunityProject = AsBuiltReport es un proyecto de código abierto mantenido por la comunidad. No tiene patrocinio, respaldo ni afiliación con ningún proveedor de tecnología, sus empleados o afiliados. + ReportModuleInstalled = {0} {1} está actualmente instalado. + ReportModuleAvailable = {0} {1} está disponible. + ReportModuleUpdate = Ejecute 'Update-Module -Name {0} -Force' para instalar la última versión. + RequiredModuleNotInstalled = Se requiere {0} {1} o superior. Ejecute 'Install-Module -Name {0} -RequiredVersion {1} -AllowClobber' para instalar el módulo requerido. + RequiredModuleTooOld = {0} {1} está actualmente instalado. Se requiere {0} {2} o superior. Ejecute 'Update-Module -Name {0} -RequiredVersion {2} -Force' para actualizar a la versión requerida. +'@ \ No newline at end of file diff --git a/AsBuiltReport.Core/Language/es-ES/New-AsBuiltReportConfig.psd1 b/AsBuiltReport.Core/Language/es-ES/New-AsBuiltReportConfig.psd1 new file mode 100644 index 0000000..e65e8c3 --- /dev/null +++ b/AsBuiltReport.Core/Language/es-ES/New-AsBuiltReportConfig.psd1 @@ -0,0 +1,11 @@ +# culture = 'es-ES' +ConvertFrom-StringData @' + FolderNotExist = La carpeta '{0}' no existe. Créela y ejecútela New-AsBuiltReportConfig de nuevo. + ProcessConfig = Procesando archivo de configuración de informe {0} del módulo {1}, versión {2}. + CopyConfig = Copiando el archivo de configuración del informe '{0}' a '{1}'. + CopyModuleConfig = Copiando {0} archivo de configuración de informe '{1}' a '{2}'. + CreateConfig = {0} Archivo de configuración de informe '{1}.json' creado en '{2}'. + OverWriteConfig = Copiando el archivo de configuración del informe '{0})' a '{1}'. Sobrescribiendo el archivo existente. + ForceOverwrite = El archivo de configuración del informe {0} '{1}.json' ya existe en '{2}'. Use '-Force' para sobrescribir el archivo existente. + ConfigNotFound = Archivo de configuración del informe no encontrado en la ruta del módulo '{0}'. +'@ \ No newline at end of file diff --git a/AsBuiltReport.Core/Language/fi-FI/AsBuiltReportCoreStyle.psd1 b/AsBuiltReport.Core/Language/fi-FI/AsBuiltReportCoreStyle.psd1 new file mode 100644 index 0000000..086c072 --- /dev/null +++ b/AsBuiltReport.Core/Language/fi-FI/AsBuiltReportCoreStyle.psd1 @@ -0,0 +1,11 @@ +# culture = 'fi-FI' +ConvertFrom-StringData @' + Footer = Sivu + Logo = AsBuiltReport Logo + CoverPageWarning = Kansikuvaa ei voida näyttää. Aseta 'ShowCoverPageImage' arvoon 'false' raportin JSON-määritystiedostossa tämän virheen välttämiseksi. + CoverPage = Kansilehti + Author = Tekijä: + Date = Päivämäärä: + Version = Versio: + TOC = Sisällysluettelo +'@ diff --git a/AsBuiltReport.Core/Language/fi-FI/New-AsBuiltConfig.psd1 b/AsBuiltReport.Core/Language/fi-FI/New-AsBuiltConfig.psd1 new file mode 100644 index 0000000..94e74ed --- /dev/null +++ b/AsBuiltReport.Core/Language/fi-FI/New-AsBuiltConfig.psd1 @@ -0,0 +1,58 @@ +# culture = 'fi-FI' +@{ + +# As Built Report Information +ReportInfo = ConvertFrom-StringData @' + BannerTitle = As Built Report Tiedot + ReportAuthor = Anna tämän As Built Report tekijän nimi [{0}] +'@ + +# Company Configuration +CompanyConfig = ConvertFrom-StringData @' + BannerTitle = Yrityksen Tiedot + CompanyInfo = Haluatko syöttää yrityksen tiedot As Built Report -raporttiin? (y/N) + CompanyFullName = Anna yrityksen koko nimi + CompanyShortName = Anna yrityksen lyhyt nimi + CompanyContact = Anna yrityksen yhteystieto + CompanyEmail = Anna yrityksen sähköpostiosoite + CompanyPhone = Anna yrityksen puhelinnumero + CompanyAddress = Anna yrityksen osoite +'@ + +# Email Configuration +EmailConfig = ConvertFrom-StringData @' + BannerTitle = Sähköpostiasetukset + ConfigureMailSettings = Haluatko syöttää SMTP-asetukset? (y/N) + MailServer = Anna sähköpostipalvelimen FQDN / IP-osoite + EmptyMailServerAddress = Sähköpostipalvelimen osoite ei voi olla tyhjä. Anna kelvollinen sähköpostipalvelimen FQDN / IP-osoite. + InvalidMailServer = '{0}' ei ole kelvollinen FQDN tai IP-osoite. Anna kelvollinen sähköpostipalvelimen FQDN / IP-osoite. + MailServerPort587 = Anna sähköpostipalvelimen porttinumero [587] + InvalidMailServerPort587 = Virheellinen porttinumero. Anna numero välillä 1 - 65535 tai paina Enter käyttääksesi oletusarvoa [587]. + MailServerPort25 = Anna sähköpostipalvelimen porttinumero [25] + InvalidMailServerPort25 = Virheellinen porttinumero. Anna numero välillä 1 - 65535 tai paina Enter käyttääksesi oletusarvoa [25]. + MailServerUseSSL = Käytetäänkö SSL:ää sähköpostipalvelinyhteyteen? (y/N) + MailCredentials = Vaatiiko sähköpostipalvelin todennuksen? (y/N) + MailFrom = Anna lähettäjän sähköpostiosoite + MailTo = Anna vastaanottajan sähköpostiosoite + EmptyEmail = Sähköpostiosoite ei voi olla tyhjä. Anna kelvollinen sähköpostiosoite. + InvalidEmail = '{0}' ei ole kelvollinen sähköpostiosoite. Anna kelvollinen sähköpostiosoite. + AnotherRecipient = Haluatko lisätä toisen vastaanottajan? (y/N) + MailBodyPrompt = Anna sähköpostiviestin sisältö + MailBody = As Built Report liitteenä +'@ + +# Report Configuration +ReportConfig = ConvertFrom-StringData @' + BannerTitle = As Built Report Asetukset + ReportConfigFolder = Anna kansion koko polku, jota käytetään raporttiasetustiedostojen ja mukautettujen tyyliskriptien tallentamiseen [{0}] + OverwriteReportConfig = Raporttimoduulin asetustiedosto kohteelle {0} on jo olemassa määritetyssä kansiossa. Haluatko korvata sen? (y/N) + CopyFile = Kopioidaan '{0}' kohteeseen '{1}'. + OverwriteFile = Kopioidaan '{0}' kohteeseen '{1}'. Korvataan olemassa oleva tiedosto. + SaveAsBuiltConfig = Haluatko tallentaa As Built Report ydinmoduulin asetustiedoston? (Y/n) + AsBuiltName = Anna nimi As Built Report asetustiedostolle [AsBuiltReport] + AsBuiltExportPath = Anna polku As Built Report asetustiedoston tallentamiseen [{0}] + ConfigFolder = Luodaan As Built Report asetuskansio '{0}'. + SaveConfig = Tallennetaan As Built Report asetustiedosto '{0}.json' polkuun '{1}'. + NotSaved = As Built Report asetustiedostoa ei tallennettu. +'@ +} diff --git a/AsBuiltReport.Core/Language/fi-FI/New-AsBuiltReport.psd1 b/AsBuiltReport.Core/Language/fi-FI/New-AsBuiltReport.psd1 new file mode 100644 index 0000000..96119a9 --- /dev/null +++ b/AsBuiltReport.Core/Language/fi-FI/New-AsBuiltReport.psd1 @@ -0,0 +1,40 @@ +# culture = 'fi-FI' +ConvertFrom-StringData @' + PwshISE = AsBuiltReportia ei voi suorittaa Windows PowerShell ISE:stä. Käytä sen sijaan PowerShell-komentoikkunaa. + Password = Salasana käyttäjälle {0} + OutputFolderPath = OutputFolderPath '{0}' ei ole kelvollinen kansion polku. + LoadConfig = Ladataan As Built Report -määritystä kohteesta {0}. + NoConfigFound = As Built Report -määritystä ei löytynyt polusta '{0}'. + GeneratingReport = Luodaan uutta As Built Report -määritystä. + StyleScriptNotFound = Raportin tyyliskriptiä ei löytynyt polusta '{0}'. + ReportModuleNotFound = {0} raportin määritystiedostoa ei löytynyt polusta '{1}'. + LoadingReportConfig = Ladataan {0} raportin määritystiedostoa polusta '{1}'. + ReportConfigNotFound = Raportin määritystä ei löytynyt moduulin polusta '{0}'. + SetReportFileName = Asetetaan raportin tiedostonimeksi '{0}'. + EmailBannerTitle = Sähköpostipalvelimen tunnistetiedot + EmailCredentials = Syötä tunnistetiedot kohteelle {0}. + InstalledModule = AsBuiltReport.Core {0} on tällä hetkellä asennettuna. + AvailableModule = AsBuiltReport.Core {0} on saatavilla. + UpdateModule = Suorita 'Update-Module -Name AsBuiltReport.Core -Force' asentaaksesi uusimman version. + ReportGenerating = Odota, kun {0} As Built Report -raporttia luodaan. + ReportInitializing = > Alustetaan raportointikehystä... + DocumentStyle = > Ladataan asiakirjan tyyliä... + TargetSystem = > Yhdistetään kohdejärjestelmään ja kerätään tietoja... + ExecutionFailed = Raporttimoduulin suoritus epäonnistui: {0} + BuildingDocument = > Rakennetaan asiakirjan rakennetta... + ExportingDocument = > Viedään asiakirjaa... + Failed = [EPÄONNISTUI] Raportin luonti epäonnistui + ReportStyleScript = Suoritetaan raportin tyyliskriptiä polusta '{0}'. + InteractiveAuth = Interaktiivinen todennus on käytössä. Tarkista todennusikkunat todentuaksesi kohdejärjestelmään. + OutputFolder = {0} As Built Report '{1}' on tallennettu kohteeseen '{2}'. + ReportModuleInfo1 = Dokumentaatio: https://github.com/AsBuiltReport/AsBuiltReport.{0} + ReportModuleInfo2 = Ongelmat tai virheilmoitukset: https://github.com/AsBuiltReport/AsBuiltReport.{0}/issues + ReportModuleInfo3 = Muista päivittää raportin määritystiedosto jokaisen uuden version julkaisun jälkeen: https://www.asbuiltreport.com/user-guide/new-asbuiltreportconfig/ + ProjectWebsite = Katso AsBuiltReport-projektin verkkosivusto lisätietoja varten: https://www.asbuiltreport.com + CommunityProject = AsBuiltReport on yhteisön ylläpitämä avoimen lähdekoodin projekti. Sillä ei ole sponsorointia, tukea tai yhteyttä mihinkään teknologiatoimittajiin, heidän työntekijöihinsä tai yhteistyökumppaneihinsa. + ReportModuleInstalled = {0} {1} on tällä hetkellä asennettuna. + ReportModuleAvailable = {0} {1} on saatavilla. + ReportModuleUpdate = Suorita 'Update-Module -Name {0} -Force' asentaaksesi uusimman version. + RequiredModuleNotInstalled = {0} {1} tai uudempi vaaditaan. Suorita 'Install-Module -Name {0} -RequiredVersion {1} -AllowClobber' asentaaksesi vaaditun moduulin. + RequiredModuleTooOld = {0} {1} on tällä hetkellä asennettuna. {0} {2} tai uudempi vaaditaan. Suorita 'Update-Module -Name {0} -RequiredVersion {2} -Force' päivittääksesi vaadittuun versioon. +'@ diff --git a/AsBuiltReport.Core/Language/fi-FI/New-AsBuiltReportConfig.psd1 b/AsBuiltReport.Core/Language/fi-FI/New-AsBuiltReportConfig.psd1 new file mode 100644 index 0000000..5aa7f15 --- /dev/null +++ b/AsBuiltReport.Core/Language/fi-FI/New-AsBuiltReportConfig.psd1 @@ -0,0 +1,11 @@ +# culture = 'fi-FI' +ConvertFrom-StringData @' + FolderNotExist = Kansiota '{0}' ei ole olemassa. Luo kansio ja suorita New-AsBuiltReportConfig uudelleen. + ProcessConfig = Käsitellään {0} raportin määritystiedostoa moduulista {1}, versio {2}. + CopyConfig = Kopioidaan raportin määritystiedosto '{0}' kohteeseen '{1}'. + CopyModuleConfig = Kopioidaan {0} raportin määritystiedosto '{1}' kohteeseen '{2}'. + CreateConfig = {0} raportin määritystiedosto '{1}.json' luotu kohteeseen '{2}'. + OverWriteConfig = Kopioidaan raportin määritystiedosto '{0}' kohteeseen '{1}'. Korvataan olemassa oleva tiedosto. + ForceOverwrite = {0} raportin määritystiedosto '{1}.json' on jo olemassa kohteessa '{2}'. Käytä '-Force' korvataksesi olemassa oleva tiedosto. + ConfigNotFound = Raportin määritystiedostoa ei löytynyt moduulipolusta '{0}'. +'@ diff --git a/AsBuiltReport.Core/Language/fr-FR/AsBuiltReportCoreStyle.psd1 b/AsBuiltReport.Core/Language/fr-FR/AsBuiltReportCoreStyle.psd1 new file mode 100644 index 0000000..fabc354 --- /dev/null +++ b/AsBuiltReport.Core/Language/fr-FR/AsBuiltReportCoreStyle.psd1 @@ -0,0 +1,11 @@ +# culture = 'fr-FR' +ConvertFrom-StringData @' + Footer = Page + Logo = AsBuiltReport Logo + CoverPageWarning = Impossible d'afficher l'image de couverture. Veuillez définir 'ShowCoverPageImage' sur 'false' dans le fichier de configuration JSON du rapport pour éviter cette erreur. + CoverPage = Page de couverture + Author = Auteur: + Date = Date: + Version = Version: + TOC = Table des Matières +'@ \ No newline at end of file diff --git a/AsBuiltReport.Core/Language/fr-FR/New-AsBuiltConfig.psd1 b/AsBuiltReport.Core/Language/fr-FR/New-AsBuiltConfig.psd1 new file mode 100644 index 0000000..dc988f1 --- /dev/null +++ b/AsBuiltReport.Core/Language/fr-FR/New-AsBuiltConfig.psd1 @@ -0,0 +1,58 @@ +# culture = 'fr-FR' +@{ + +# Informations sur le rapport tel que construit +ReportInfo = ConvertFrom-StringData @' + BannerTitle = Informations sur le rapport tel que construit + ReportAuthor = Saisissez le nom de l'auteur de ce rapport tel que construit [{0}] +'@ + +# Configuration de l'entreprise +CompanyConfig = ConvertFrom-StringData @' + BannerTitle = Information de l'entreprise + CompanyInfo = Souhaitez-vous saisir les informations de l'entreprise pour le rapport As Built ? (y/N) + CompanyFullName = Entrez le nom complet de l'entreprise + CompanyShortName = Entrez le nom abrégé de l'entreprise + CompanyContact = Entrez le contact de l'entreprise + CompanyEmail = Entrez l'adresse e-mail de l'entreprise + CompanyPhone = Entrez le numéro de téléphone de l'entreprise + CompanyAddress = Entrez l'adresse de l'entreprise +'@ + +# Configuration de la messagerie électronique +EmailConfig = ConvertFrom-StringData @' + BannerTitle = Configuration de la messagerie électronique + ConfigureMailSettings = Souhaitez-vous configurer le SMTP ? (y/N) + MailServer = Entrez le FQDN / l'adresse IP du serveur de messagerie + EmptyMailServerAddress = L'adresse du serveur de messagerie ne peut pas être vide. Veuillez saisir un nom de domaine complet (FQDN) ou une adresse IP valide. + InvalidMailServer = {0} n'est pas un nom de domaine complet (FQDN) ni une adresse IP valide. Veuillez saisir un nom de domaine complet (FQDN) ou une adresse IP de serveur de messagerie valide. + MailServerPort587 = Entrez le numéro de port du serveur de messagerie [587] + InvalidMailServerPort587 = Numéro de port non valide. Veuillez saisir un numéro compris entre 1 et 65535, ou appuyez sur Entrée pour la valeur par défaut. [587]. + MailServerPort25 = Entrez le numéro de port du serveur de messagerie [25] + InvalidMailServerPort25 = Numéro de port non valide. Veuillez saisir un numéro compris entre 1 et 65535, ou appuyez sur Entrée pour la valeur par défaut. [25]. + MailServerUseSSL = Utiliser SSL pour la connexion au serveur de messagerie? (y/N) + MailCredentials = Exiger une authentification du serveur de messagerie? (y/N) + MailFrom = Saisissez l'adresse e-mail de l'expéditeur du courrier + MailTo = Saisissez l'adresse e-mail du destinataire du serveur de messagerie + EmptyEmail = L'adresse e-mail ne peut pas être vide. Veuillez saisir une adresse e-mail valide. + InvalidEmail = '{0}' n'est pas une adresse e-mail valide. Veuillez saisir une adresse e-mail valide. + AnotherRecipient = Voulez-vous saisir un autre destinataire? (y/N) + MailBodyPrompt = Saisissez le contenu du corps du message électronique + MailBody = Rapport de construction ci-joint +'@ + +# Configuration du rapport +ReportConfig = ConvertFrom-StringData @' + BannerTitle = Configuration du rapport tel que construit + ReportConfigFolder = Saisissez le chemin complet du dossier à utiliser pour stocker les fichiers de configuration du module de rapport et les scripts de style personnalisés [{0}] + OverwriteReportConfig = Un fichier de configuration du module de rapport pour {0} existe déjà dans le dossier spécifié. Souhaitez-vous le remplacer? (y/N) + CopyFile = Copie de '{0}' vers '{1}'. + OverwriteFile = Copie de '{0}' vers '{1}'. Écrasement du fichier existant. + SaveAsBuiltConfig = Souhaitez-vous enregistrer le fichier de configuration du module principal du rapport As Built ? (Y/n) + AsBuiltName = Entrez un nom pour le fichier de configuration du rapport As Built [AsBuiltReport] + AsBuiltExportPath = Entrez le chemin pour enregistrer le fichier de configuration du rapport As Built [{0}] + ConfigFolder = Création d'un dossier de configuration de rapport tel que construit '{0}'. + SaveConfig = Enregistrement du fichier de configuration du rapport tel que construit '{0}.json' dans le chemin '{1}'. + NotSaved = Le fichier de configuration du rapport tel que construit n'est pas enregistré. +'@ +} \ No newline at end of file diff --git a/AsBuiltReport.Core/Language/fr-FR/New-AsBuiltReport.psd1 b/AsBuiltReport.Core/Language/fr-FR/New-AsBuiltReport.psd1 new file mode 100644 index 0000000..9d27ad5 --- /dev/null +++ b/AsBuiltReport.Core/Language/fr-FR/New-AsBuiltReport.psd1 @@ -0,0 +1,40 @@ +# culture = 'fr-FR' +ConvertFrom-StringData @' + PwshISE = AsBuiltReport ne peut pas être exécuté depuis Windows PowerShell ISE. Veuillez utiliser une fenêtre de commande PowerShell. + Password = Mot de passe pour l'utilisateur {0} + OutputFolderPath = OutputFolderPath '{0}' n'est pas un chemin de dossier valide. + LoadConfig = Chargement de la configuration du rapport tel que fournit à partir de {0}. + NoConfigFound = Impossible de trouver la configuration du rapport tel que fournit dans le chemin {0}. + GeneratingReport = Génération d'une nouvelle configuration de rapport tel que fournit. + StyleScriptNotFound = Impossible de trouver le script de style de rapport dans le chemin {0}. + ReportModuleNotFound = Impossible de trouver le fichier de configuration du rapport {0} dans le chemin {1}. + LoadingReportConfig = Chargement du fichier de configuration du rapport {0} à partir du chemin {1}. + ReportConfigNotFound = La configuration du rapport n'a pas été trouvée dans le chemin du module '{0}'. + SetReportFileName = Définition du nom du fichier de rapport sur {0}. + EmailBannerTitle = Informations d'identification du serveur de messagerie + EmailCredentials = Veuillez saisir les informations d'identification pour {0}. + InstalledModule = AsBuiltReport.Core {0} est actuellement installé. + AvailableModule = AsBuiltReport.Core {0} est disponible. + UpdateModule = Exécutez 'Update-Module -Name AsBuiltReport.Core -Force' pour installer la dernière version. + ReportGenerating = Veuillez patienter pendant que le rapport {0} tel que fournit est en cours de génération. + ReportInitializing = > Initialisation du cadre de rapport... + DocumentStyle = > Chargement du style de document... + TargetSystem = > Connexion au système cible et collecte de données... + ExecutionFailed = L'exécution du module de rapport a échoué: {0} + BuildingDocument = > Construction de la structure du document... + ExportingDocument = > Exportation du document... + Failed = [ÉCHEC] La génération du rapport a échoué + ReportStyleScript = Exécution du script de style de rapport à partir du chemin {0}. + InteractiveAuth = L'authentification interactive est activée. Veuillez vérifier les fenêtres d'authentification pour vous authentifier sur votre système cible. + OutputFolder = {0} Le rapport tel que fournit {1} a été enregistré dans {2}. + ReportModuleInfo1 = Documentation : https://github.com/AsBuiltReport/AsBuiltReport.{0} + ReportModuleInfo2 = Problèmes ou signalement de bogues : https://github.com/AsBuiltReport/AsBuiltReport.{0}/issues + ReportModuleInfo3 = N'oubliez pas de mettre à jour votre fichier de configuration de rapport après chaque nouvelle version : https://www.asbuiltreport.com/user-guide/new-asbuiltreportconfig/ + ProjectWebsite = Veuillez consulter le site Web du projet AsBuiltReport pour des informations plus détaillées : https://www.asbuiltreport.com + CommunityProject = AsBuiltReport est un projet open source maintenu par la communauté. Il n'a aucun parrainage, approbation ou affiliation avec des fournisseurs de technologie, leurs employés ou affiliés. + ReportModuleInstalled = {0} {1} est actuellement installé. + ReportModuleAvailable = {0} {1} est disponible. + ReportModuleUpdate = Exécutez 'Update-Module -Name {0} -Force' pour installer la dernière version. + RequiredModuleNotInstalled = {0} {1} ou supérieur est requis. Exécutez 'Install-Module -Name {0} -RequiredVersion {1} -AllowClobber' pour installer le module requis. + RequiredModuleTooOld = {0} {1} est actuellement installé. {0} {2} ou supérieur est requis. Exécutez 'Update-Module -Name {0} -RequiredVersion {2} -Force' pour mettre à jour vers la version requise. +'@ \ No newline at end of file diff --git a/AsBuiltReport.Core/Language/fr-FR/New-AsBuiltReportConfig.psd1 b/AsBuiltReport.Core/Language/fr-FR/New-AsBuiltReportConfig.psd1 new file mode 100644 index 0000000..84ee538 --- /dev/null +++ b/AsBuiltReport.Core/Language/fr-FR/New-AsBuiltReportConfig.psd1 @@ -0,0 +1,11 @@ +# culture = 'fr-FR' +ConvertFrom-StringData @' + FolderNotExist = Le dossier {0} n'existe pas. Veuillez le créer et réexécuter New-AsBuiltReportConfig. + ProcessConfig = Traitement du fichier de configuration du rapport {0} du module {1}, version {2}. + CopyConfig = Copie du fichier de configuration du rapport '{0}' vers '{1}'. + CopyModuleConfig = Copie du fichier de configuration du rapport {0} '{1}' vers '{2}'. + CreateConfig = {0} fichier de configuration du rapport '{1}.json' créé dans '{2}'. + OverWriteConfig = Copie du fichier de configuration du rapport {0} vers {1}. Écrasement du fichier existant. + ForceOverwrite = Le fichier de configuration du rapport {0} '{1}.json' existe déjà dans '{2}'. Utilisez '-Force' pour écraser le fichier existant. + ConfigNotFound = Le fichier de configuration du rapport n'a pas été trouvé dans le chemin du module '{0}'. +'@ \ No newline at end of file diff --git a/AsBuiltReport.Core/Language/he-IL/AsBuiltReportCoreStyle.psd1 b/AsBuiltReport.Core/Language/he-IL/AsBuiltReportCoreStyle.psd1 new file mode 100644 index 0000000..7e6dc98 --- /dev/null +++ b/AsBuiltReport.Core/Language/he-IL/AsBuiltReportCoreStyle.psd1 @@ -0,0 +1,11 @@ +# culture = 'he-IL' +ConvertFrom-StringData @' + Footer = עמוד + Logo = לוגו AsBuiltReport + CoverPageWarning = לא ניתן להציג את תמונת עמוד השער. אנא הגדר את 'ShowCoverPageImage' ל-'false' בקובץ התצורה JSON של הדוח כדי למנוע שגיאה זו. + CoverPage = עמוד שער + Author = מחבר: + Date = תאריך: + Version = גרסה: + TOC = תוכן עניינים +'@ diff --git a/AsBuiltReport.Core/Language/he-IL/New-AsBuiltConfig.psd1 b/AsBuiltReport.Core/Language/he-IL/New-AsBuiltConfig.psd1 new file mode 100644 index 0000000..14b9604 --- /dev/null +++ b/AsBuiltReport.Core/Language/he-IL/New-AsBuiltConfig.psd1 @@ -0,0 +1,58 @@ +# culture = 'he-IL' +@{ + +# As Built Report Information +ReportInfo = ConvertFrom-StringData @' + BannerTitle = מידע על דוח As Built + ReportAuthor = הזן את שם המחבר של דוח As Built זה [{0}] +'@ + +# Company Configuration +CompanyConfig = ConvertFrom-StringData @' + BannerTitle = מידע על החברה + CompanyInfo = האם ברצונך להזין מידע על החברה עבור דוח As Built? (y/N) + CompanyFullName = הזן את השם המלא של החברה + CompanyShortName = הזן את השם המקוצר של החברה + CompanyContact = הזן את איש הקשר בחברה + CompanyEmail = הזן את כתובת הדוא"ל של החברה + CompanyPhone = הזן את מספר הטלפון של החברה + CompanyAddress = הזן את כתובת החברה +'@ + +# Email Configuration +EmailConfig = ConvertFrom-StringData @' + BannerTitle = תצורת דוא"ל + ConfigureMailSettings = האם ברצונך להזין תצורת SMTP? (y/N) + MailServer = הזן את FQDN / כתובת IP של שרת הדוא"ל + EmptyMailServerAddress = כתובת שרת הדוא"ל לא יכולה להיות רקה. אנא הזן FQDN / כתובת IP תקינה של שרת דוא"ל. + InvalidMailServer = '{0}' אינו FQDN או כתובת IP תקינה. אנא הזן FQDN / כתובת IP תקינה של שרת דוא"ל. + MailServerPort587 = הזן את מספר הפורט של שרת הדוא"ל [587] + InvalidMailServerPort587 = מספר פורט לא תקין. אנא הזן מספר בין 1 ל-65535, או לחץ Enter עבור ברירת המחדל [587]. + MailServerPort25 = הזן את מספר הפורט של שרת הדוא"ל [25] + InvalidMailServerPort25 = מספר פורט לא תקין. אנא הזן מספר בין 1 ל-65535, או לחץ Enter עבור ברירת המחדל [25]. + MailServerUseSSL = האם להשתמש ב-SSL עבור חיבור לשרת דוא"ל? (y/N) + MailCredentials = האם נדרש אימות לשרת הדוא"ל? (y/N) + MailFrom = הזן את כתובת הדוא"ל של השולח + MailTo = הזן את כתובת הדוא"ל של הנמען + EmptyEmail = כתובת דוא"ל לא יכולה להיות רקה. אנא הזן כתובת דוא"ל תקינה. + InvalidEmail = '{0}' אינה כתובת דוא"ל תקינה. אנא הזן כתובת דוא"ל תקינה. + AnotherRecipient = האם ברצונך להזין נמען נוסף? (y/N) + MailBodyPrompt = הזן את תוכן גוף הודעת הדוא"ל + MailBody = דוח As Built מצורף +'@ + +# Report Configuration +ReportConfig = ConvertFrom-StringData @' + BannerTitle = תצורת דוח As Built + ReportConfigFolder = הזן את הנתיב המלא של התיקייה לאחסון קבצי תצורת מודול הדוח וסקריפטים מותאמים אישית של סגנון [{0}] + OverwriteReportConfig = קובץ תצורת מודול דוח עבור {0} כבר קיים בתיקייה שצוינה. האם ברצונך לדרוס אותו? (y/N) + CopyFile = מעתיק את '{0}' אל '{1}'. + OverwriteFile = מעתיק את '{0}' אל '{1}'. דורס קובץ קיים. + SaveAsBuiltConfig = האם ברצונך לשמור את קובץ התצורה של מודול הליבה של As Built Report? (Y/n) + AsBuiltName = הזן שם עבור קובץ תצורת As Built Report [AsBuiltReport] + AsBuiltExportPath = הזן את הנתיב לשמירת קובץ תצורת As Built Report [{0}] + ConfigFolder = יוצר תיקיית תצורת As Built Report '{0}'. + SaveConfig = שומר קובץ תצורת As Built Report '{0}.json' בנתיב '{1}'. + NotSaved = קובץ תצורת As Built Report לא נשמר. +'@ +} diff --git a/AsBuiltReport.Core/Language/he-IL/New-AsBuiltReport.psd1 b/AsBuiltReport.Core/Language/he-IL/New-AsBuiltReport.psd1 new file mode 100644 index 0000000..794c2c2 --- /dev/null +++ b/AsBuiltReport.Core/Language/he-IL/New-AsBuiltReport.psd1 @@ -0,0 +1,40 @@ +# culture = 'he-IL' +ConvertFrom-StringData @' + PwshISE = לא ניתן להריץ את AsBuiltReport מתוך Windows PowerShell ISE. אנא השתמש בחלון פקודות PowerShell במקום זאת. + Password = סיסמה עבור משתמש {0} + OutputFolderPath = OutputFolderPath '{0}' אינו נתיב תיקייה תקין. + LoadConfig = טוען תצורת As Built Report מ-{0}. + NoConfigFound = לא נמצאה תצורת As Built Report בנתיב '{0}'. + GeneratingReport = יוצר תצורת As Built Report חדשה. + StyleScriptNotFound = לא נמצא סקריפט סגנון הדוח בנתיב '{0}'. + ReportModuleNotFound = לא נמצא קובץ תצורת דוח {0} בנתיב '{1}'. + LoadingReportConfig = טוען קובץ תצורת דוח {0} מנתיב '{1}'. + ReportConfigNotFound = תצורת הדוח לא נמצאה בנתיב המודול '{0}'. + SetReportFileName = מגדיר את שם קובץ הדוח ל-'{0}'. + EmailBannerTitle = אישורי שרת דוא"ל + EmailCredentials = אנא הזן אישורים עבור {0}. + InstalledModule = AsBuiltReport.Core {0} מותקן כרגע. + AvailableModule = AsBuiltReport.Core {0} זמין. + UpdateModule = הרץ 'Update-Module -Name AsBuiltReport.Core -Force' כדי להתקין את הגרסה העדכנית ביותר. + ReportGenerating = אנא המתן בעוד דוח As Built של {0} נוצר. + ReportInitializing = > מאתחל מסגרת דוח... + DocumentStyle = > טוען סגנון מסמך... + TargetSystem = > מתחבר למערכת היעד ואוסף נתונים... + ExecutionFailed = ביצוע מודול הדוח נכשל: {0} + BuildingDocument = > בונה מבנה מסמך... + ExportingDocument = > מייצא מסמך... + Failed = [FAILED] יצירת הדוח נכשלה + ReportStyleScript = מבצע סקריפט סגנון דוח מנתיב '{0}'. + InteractiveAuth = אימות אינטראקטיבי מופעל. אנא בדוק חלונות אימות כדי להזדהות למערכת היעד שלך. + OutputFolder = דוח As Built של {0} '{1}' נשמר ב-'{2}'. + ReportModuleInfo1 = תיעוד: https://github.com/AsBuiltReport/AsBuiltReport.{0} + ReportModuleInfo2 = דיווח על בעיות או באגים: https://github.com/AsBuiltReport/AsBuiltReport.{0}/issues + ReportModuleInfo3 = אל תשכח לעדכן את קובץ תצורת הדוח שלך לאחר כל שחרור גרסה חדשה: https://www.asbuiltreport.com/user-guide/new-asbuiltreportconfig/ + ProjectWebsite = אנא עיין באתר הפרויקט של AsBuiltReport למידע מפורט יותר: https://www.asbuiltreport.com + CommunityProject = AsBuiltReport הוא פרויקט קוד פתוח המתוחזק על ידי הקהילה. אין לו חסות, אישור או זיקה לספקי טכנולוגיה כלשהם, עובדיהם או שותפיהם. + ReportModuleInstalled = {0} {1} מותקן כרגע. + ReportModuleAvailable = {0} {1} זמין. + ReportModuleUpdate = הרץ 'Update-Module -Name {0} -Force' כדי להתקין את הגרסה העדכנית ביותר. + RequiredModuleNotInstalled = נדרש {0} {1} או גבוה יותר. הרץ 'Install-Module -Name {0} -RequiredVersion {1} -AllowClobber' כדי להתקין את המודול הנדרש. + RequiredModuleTooOld = {0} {1} מותקן כרגע. נדרש {0} {2} או גבוה יותר. הרץ 'Update-Module -Name {0} -RequiredVersion {2} -Force' כדי לעדכן לגרסה הנדרשת. +'@ diff --git a/AsBuiltReport.Core/Language/he-IL/New-AsBuiltReportConfig.psd1 b/AsBuiltReport.Core/Language/he-IL/New-AsBuiltReportConfig.psd1 new file mode 100644 index 0000000..5953289 --- /dev/null +++ b/AsBuiltReport.Core/Language/he-IL/New-AsBuiltReportConfig.psd1 @@ -0,0 +1,11 @@ +# culture = 'he-IL' +ConvertFrom-StringData @' + FolderNotExist = התיקייה '{0}' לא קיימת. אנא צור את התיקייה והרץ את New-AsBuiltReportConfig שוב. + ProcessConfig = מעבד קובץ תצורת דוח {0} ממודול {1}, גרסה {2}. + CopyConfig = מעתיק קובץ תצורת דוח '{0}' אל '{1}'. + CopyModuleConfig = מעתיק קובץ תצורת דוח {0} '{1}' אל '{2}'. + CreateConfig = קובץ תצורת דוח {0} '{1}.json' נוצר ב-'{2}'. + OverWriteConfig = מעתיק קובץ תצורת דוח '{0})' אל '{1}'. דורס קובץ קיים. + ForceOverwrite = קובץ תצורת דוח {0} '{1}.json' כבר קיים ב-'{2}'. השתמש ב-'-Force' כדי לדרוס קובץ קיים. + ConfigNotFound = קובץ תצורת דוח לא נמצא בנתיב המודול '{0}'. +'@ diff --git a/AsBuiltReport.Core/Language/hi-IN/AsBuiltReportCoreStyle.psd1 b/AsBuiltReport.Core/Language/hi-IN/AsBuiltReportCoreStyle.psd1 new file mode 100644 index 0000000..e18f832 --- /dev/null +++ b/AsBuiltReport.Core/Language/hi-IN/AsBuiltReportCoreStyle.psd1 @@ -0,0 +1,11 @@ +# culture = 'hi-IN' +ConvertFrom-StringData @' + Footer = पृष्ठ + Logo = AsBuiltReport लोगो + CoverPageWarning = कवर पेज छवि प्रदर्शित करने में असमर्थ। कृपया इस त्रुटि से बचने के लिए रिपोर्ट JSON कॉन्फ़िगरेशन फ़ाइल में 'ShowCoverPageImage' को 'false' पर सेट करें। + CoverPage = कवर पेज + Author = लेखक: + Date = दिनांक: + Version = संस्करण: + TOC = विषय सूची +'@ diff --git a/AsBuiltReport.Core/Language/hi-IN/New-AsBuiltConfig.psd1 b/AsBuiltReport.Core/Language/hi-IN/New-AsBuiltConfig.psd1 new file mode 100644 index 0000000..34dbc18 --- /dev/null +++ b/AsBuiltReport.Core/Language/hi-IN/New-AsBuiltConfig.psd1 @@ -0,0 +1,58 @@ +# culture = 'hi-IN' +@{ + +# As Built Report Information +ReportInfo = ConvertFrom-StringData @' + BannerTitle = As Built Report जानकारी + ReportAuthor = इस As Built Report के लेखक का नाम दर्ज करें [{0}] +'@ + +# Company Configuration +CompanyConfig = ConvertFrom-StringData @' + BannerTitle = कंपनी की जानकारी + CompanyInfo = क्या आप As Built Report के लिए कंपनी की जानकारी दर्ज करना चाहेंगे? (y/N) + CompanyFullName = कंपनी का पूरा नाम दर्ज करें + CompanyShortName = कंपनी का संक्षिप्त नाम दर्ज करें + CompanyContact = कंपनी संपर्क दर्ज करें + CompanyEmail = कंपनी का ईमेल पता दर्ज करें + CompanyPhone = कंपनी का फोन नंबर दर्ज करें + CompanyAddress = कंपनी का पता दर्ज करें +'@ + +# Email Configuration +EmailConfig = ConvertFrom-StringData @' + BannerTitle = ईमेल कॉन्फ़िगरेशन + ConfigureMailSettings = क्या आप SMTP कॉन्फ़िगरेशन दर्ज करना चाहेंगे? (y/N) + MailServer = मेल सर्वर FQDN / IP पता दर्ज करें + EmptyMailServerAddress = मेल सर्वर पता खाली नहीं हो सकता। कृपया एक वैध मेल सर्वर FQDN / IP पता दर्ज करें। + InvalidMailServer = '{0}' एक वैध FQDN या IP पता नहीं है। कृपया एक वैध मेल सर्वर FQDN / IP पता दर्ज करें। + MailServerPort587 = मेल सर्वर पोर्ट नंबर दर्ज करें [587] + InvalidMailServerPort587 = अवैध पोर्ट नंबर। कृपया 1 और 65535 के बीच एक नंबर दर्ज करें, या डिफ़ॉल्ट [587] के लिए Enter दबाएं। + MailServerPort25 = मेल सर्वर पोर्ट नंबर दर्ज करें [25] + InvalidMailServerPort25 = अवैध पोर्ट नंबर। कृपया 1 और 65535 के बीच एक नंबर दर्ज करें, या डिफ़ॉल्ट [25] के लिए Enter दबाएं। + MailServerUseSSL = मेल सर्वर कनेक्शन के लिए SSL का उपयोग करें? (y/N) + MailCredentials = मेल सर्वर प्रमाणीकरण की आवश्यकता है? (y/N) + MailFrom = प्रेषक का ईमेल पता दर्ज करें + MailTo = प्राप्तकर्ता का ईमेल पता दर्ज करें + EmptyEmail = ईमेल पता खाली नहीं हो सकता। कृपया एक वैध ईमेल पता दर्ज करें। + InvalidEmail = '{0}' एक वैध ईमेल पता नहीं है। कृपया एक वैध ईमेल पता दर्ज करें। + AnotherRecipient = क्या आप अन्य प्राप्तकर्ता दर्ज करना चाहते हैं? (y/N) + MailBodyPrompt = ईमेल संदेश की सामग्री दर्ज करें + MailBody = As Built Report संलग्न +'@ + +# Report Configuration +ReportConfig = ConvertFrom-StringData @' + BannerTitle = As Built Report कॉन्फ़िगरेशन + ReportConfigFolder = रिपोर्ट मॉड्यूल कॉन्फ़िगरेशन फ़ाइलों और कस्टम स्टाइल स्क्रिप्ट को संग्रहीत करने के लिए फ़ोल्डर का पूरा पथ दर्ज करें [{0}] + OverwriteReportConfig = निर्दिष्ट फ़ोल्डर में {0} के लिए एक रिपोर्ट मॉड्यूल कॉन्फ़िगरेशन फ़ाइल पहले से मौजूद है। क्या आप इसे अधिलेखित करना चाहेंगे? (y/N) + CopyFile = '{0}' को '{1}' में कॉपी किया जा रहा है। + OverwriteFile = '{0}' को '{1}' में कॉपी किया जा रहा है। मौजूदा फ़ाइल को अधिलेखित किया जा रहा है। + SaveAsBuiltConfig = क्या आप As Built Report कोर मॉड्यूल कॉन्फ़िगरेशन फ़ाइल को सहेजना चाहेंगे? (Y/n) + AsBuiltName = As Built Report कॉन्फ़िगरेशन फ़ाइल के लिए एक नाम दर्ज करें [AsBuiltReport] + AsBuiltExportPath = As Built Report कॉन्फ़िगरेशन फ़ाइल को सहेजने के लिए पथ दर्ज करें [{0}] + ConfigFolder = As Built Report कॉन्फ़िगरेशन फ़ोल्डर '{0}' बनाया जा रहा है। + SaveConfig = As Built Report कॉन्फ़िगरेशन फ़ाइल '{0}.json' को पथ '{1}' में सहेजा जा रहा है। + NotSaved = As Built Report कॉन्फ़िगरेशन फ़ाइल सहेजी नहीं गई। +'@ +} diff --git a/AsBuiltReport.Core/Language/hi-IN/New-AsBuiltReport.psd1 b/AsBuiltReport.Core/Language/hi-IN/New-AsBuiltReport.psd1 new file mode 100644 index 0000000..ab65e64 --- /dev/null +++ b/AsBuiltReport.Core/Language/hi-IN/New-AsBuiltReport.psd1 @@ -0,0 +1,40 @@ +# culture = 'hi-IN' +ConvertFrom-StringData @' + PwshISE = AsBuiltReport को Windows PowerShell ISE से नहीं चलाया जा सकता। कृपया इसके बजाय PowerShell कमांड विंडो का उपयोग करें। + Password = उपयोगकर्ता {0} के लिए पासवर्ड + OutputFolderPath = OutputFolderPath '{0}' एक वैध फ़ोल्डर पथ नहीं है। + LoadConfig = {0} से As Built Report कॉन्फ़िगरेशन लोड किया जा रहा है। + NoConfigFound = पथ '{0}' में As Built Report कॉन्फ़िगरेशन नहीं मिला। + GeneratingReport = नया As Built Report कॉन्फ़िगरेशन जेनरेट किया जा रहा है। + StyleScriptNotFound = पथ '{0}' में रिपोर्ट स्टाइल स्क्रिप्ट नहीं मिली। + ReportModuleNotFound = पथ '{1}' में {0} रिपोर्ट कॉन्फ़िगरेशन फ़ाइल नहीं मिली। + LoadingReportConfig = पथ '{1}' से {0} रिपोर्ट कॉन्फ़िगरेशन फ़ाइल लोड की जा रही है। + ReportConfigNotFound = मॉड्यूल पथ '{0}' में रिपोर्ट कॉन्फ़िगरेशन नहीं मिला। + SetReportFileName = रिपोर्ट फ़ाइल का नाम '{0}' पर सेट किया जा रहा है। + EmailBannerTitle = ईमेल सर्वर क्रेडेंशियल + EmailCredentials = कृपया {0} के लिए क्रेडेंशियल दर्ज करें। + InstalledModule = AsBuiltReport.Core {0} वर्तमान में इंस्टॉल है। + AvailableModule = AsBuiltReport.Core {0} उपलब्ध है। + UpdateModule = नवीनतम संस्करण इंस्टॉल करने के लिए 'Update-Module -Name AsBuiltReport.Core -Force' चलाएं। + ReportGenerating = कृपया प्रतीक्षा करें जबकि {0} As Built Report जेनरेट किया जा रहा है। + ReportInitializing = > रिपोर्ट फ्रेमवर्क आरंभ किया जा रहा है... + DocumentStyle = > दस्तावेज़ स्टाइल लोड की जा रही है... + TargetSystem = > लक्ष्य सिस्टम से कनेक्ट किया जा रहा है और डेटा एकत्र किया जा रहा है... + ExecutionFailed = रिपोर्ट मॉड्यूल निष्पादन विफल: {0} + BuildingDocument = > दस्तावेज़ संरचना बनाई जा रही है... + ExportingDocument = > दस्तावेज़ निर्यात किया जा रहा है... + Failed = [विफल] रिपोर्ट जेनरेशन विफल + ReportStyleScript = पथ '{0}' से रिपोर्ट स्टाइल स्क्रिप्ट निष्पादित की जा रही है। + InteractiveAuth = इंटरैक्टिव प्रमाणीकरण सक्षम है। कृपया अपने लक्ष्य सिस्टम में प्रमाणित करने के लिए प्रमाणीकरण विंडो की जांच करें। + OutputFolder = {0} As Built Report '{1}' को '{2}' में सहेजा गया है। + ReportModuleInfo1 = दस्तावेज़ीकरण: https://github.com/AsBuiltReport/AsBuiltReport.{0} + ReportModuleInfo2 = समस्याएं या बग रिपोर्टिंग: https://github.com/AsBuiltReport/AsBuiltReport.{0}/issues + ReportModuleInfo3 = प्रत्येक नए संस्करण रिलीज़ के बाद अपनी रिपोर्ट कॉन्फ़िगरेशन फ़ाइल अपडेट करना न भूलें: https://www.asbuiltreport.com/user-guide/new-asbuiltreportconfig/ + ProjectWebsite = अधिक विस्तृत जानकारी के लिए कृपया AsBuiltReport प्रोजेक्ट वेबसाइट देखें: https://www.asbuiltreport.com + CommunityProject = AsBuiltReport एक समुदाय-रखरखाव ओपन सोर्स प्रोजेक्ट है। इसमें किसी भी प्रौद्योगिकी विक्रेताओं, उनके कर्मचारियों या सहयोगियों के साथ कोई प्रायोजन, समर्थन या संबद्धता नहीं है। + ReportModuleInstalled = {0} {1} वर्तमान में इंस्टॉल है। + ReportModuleAvailable = {0} {1} उपलब्ध है। + ReportModuleUpdate = नवीनतम संस्करण इंस्टॉल करने के लिए 'Update-Module -Name {0} -Force' चलाएं। + RequiredModuleNotInstalled = {0} {1} या उच्चतर आवश्यक है। आवश्यक मॉड्यूल इंस्टॉल करने के लिए 'Install-Module -Name {0} -RequiredVersion {1} -AllowClobber' चलाएं। + RequiredModuleTooOld = {0} {1} वर्तमान में इंस्टॉल है। {0} {2} या उच्चतर आवश्यक है। आवश्यक संस्करण में अपडेट करने के लिए 'Update-Module -Name {0} -RequiredVersion {2} -Force' चलाएं। +'@ diff --git a/AsBuiltReport.Core/Language/hi-IN/New-AsBuiltReportConfig.psd1 b/AsBuiltReport.Core/Language/hi-IN/New-AsBuiltReportConfig.psd1 new file mode 100644 index 0000000..89b0bec --- /dev/null +++ b/AsBuiltReport.Core/Language/hi-IN/New-AsBuiltReportConfig.psd1 @@ -0,0 +1,11 @@ +# culture = 'hi-IN' +ConvertFrom-StringData @' + FolderNotExist = फ़ोल्डर '{0}' मौजूद नहीं है। कृपया फ़ोल्डर बनाएं और New-AsBuiltReportConfig फिर से चलाएं। + ProcessConfig = मॉड्यूल {1}, संस्करण {2} से {0} रिपोर्ट कॉन्फ़िगरेशन फ़ाइल को प्रोसेस किया जा रहा है। + CopyConfig = रिपोर्ट कॉन्फ़िगरेशन फ़ाइल '{0}' को '{1}' में कॉपी किया जा रहा है। + CopyModuleConfig = {0} रिपोर्ट कॉन्फ़िगरेशन फ़ाइल '{1}' को '{2}' में कॉपी किया जा रहा है। + CreateConfig = {0} रिपोर्ट कॉन्फ़िगरेशन फ़ाइल '{1}.json' '{2}' में बनाई गई। + OverWriteConfig = रिपोर्ट कॉन्फ़िगरेशन फ़ाइल '{0}' को '{1}' में कॉपी किया जा रहा है। मौजूदा फ़ाइल को अधिलेखित किया जा रहा है। + ForceOverwrite = {0} रिपोर्ट कॉन्फ़िगरेशन फ़ाइल '{1}.json' पहले से '{2}' में मौजूद है। मौजूदा फ़ाइल को अधिलेखित करने के लिए '-Force' का उपयोग करें। + ConfigNotFound = मॉड्यूल पथ '{0}' में रिपोर्ट कॉन्फ़िगरेशन फ़ाइल नहीं मिली। +'@ diff --git a/AsBuiltReport.Core/Language/hu-HU/AsBuiltReportCoreStyle.psd1 b/AsBuiltReport.Core/Language/hu-HU/AsBuiltReportCoreStyle.psd1 new file mode 100644 index 0000000..d769bee --- /dev/null +++ b/AsBuiltReport.Core/Language/hu-HU/AsBuiltReportCoreStyle.psd1 @@ -0,0 +1,11 @@ +# culture = 'hu-HU' +ConvertFrom-StringData @' + Footer = Oldal + Logo = AsBuiltReport Logó + CoverPageWarning = Nem lehet megjeleníteni a borítólap képet. Kérjük, állítsa a 'ShowCoverPageImage' értékét 'false'-ra a jelentés JSON konfigurációs fájljában a hiba elkerülése érdekében. + CoverPage = Borítólap + Author = Szerző: + Date = Dátum: + Version = Verzió: + TOC = Tartalomjegyzék +'@ diff --git a/AsBuiltReport.Core/Language/hu-HU/New-AsBuiltConfig.psd1 b/AsBuiltReport.Core/Language/hu-HU/New-AsBuiltConfig.psd1 new file mode 100644 index 0000000..d196c2d --- /dev/null +++ b/AsBuiltReport.Core/Language/hu-HU/New-AsBuiltConfig.psd1 @@ -0,0 +1,58 @@ +# culture = 'hu-HU' +@{ + +# As Built Report Information +ReportInfo = ConvertFrom-StringData @' + BannerTitle = As Built Report Információk + ReportAuthor = Adja meg ennek az As Built Report szerzőjének nevét [{0}] +'@ + +# Company Configuration +CompanyConfig = ConvertFrom-StringData @' + BannerTitle = Cég Információk + CompanyInfo = Szeretné megadni a céginformációkat az As Built Report számára? (y/N) + CompanyFullName = Adja meg a cég teljes nevét + CompanyShortName = Adja meg a cég rövid nevét + CompanyContact = Adja meg a cég kapcsolattartóját + CompanyEmail = Adja meg a cég e-mail címét + CompanyPhone = Adja meg a cég telefonszámát + CompanyAddress = Adja meg a cég címét +'@ + +# Email Configuration +EmailConfig = ConvertFrom-StringData @' + BannerTitle = E-mail Konfiguráció + ConfigureMailSettings = Szeretné megadni az SMTP konfigurációt? (y/N) + MailServer = Adja meg a levelezőszerver FQDN / IP címét + EmptyMailServerAddress = A levelezőszerver címe nem lehet üres. Kérjük, adjon meg egy érvényes levelezőszerver FQDN / IP címét. + InvalidMailServer = A(z) '{0}' nem érvényes FQDN vagy IP cím. Kérjük, adjon meg egy érvényes levelezőszerver FQDN / IP címét. + MailServerPort587 = Adja meg a levelezőszerver portszámát [587] + InvalidMailServerPort587 = Érvénytelen portszám. Kérjük, adjon meg egy számot 1 és 65535 között, vagy nyomja meg az Enter billentyűt az alapértelmezett értékhez [587]. + MailServerPort25 = Adja meg a levelezőszerver portszámát [25] + InvalidMailServerPort25 = Érvénytelen portszám. Kérjük, adjon meg egy számot 1 és 65535 között, vagy nyomja meg az Enter billentyűt az alapértelmezett értékhez [25]. + MailServerUseSSL = SSL használata a levelezőszerver kapcsolathoz? (y/N) + MailCredentials = A levelezőszerver hitelesítést igényel? (y/N) + MailFrom = Adja meg a feladó e-mail címét + MailTo = Adja meg a címzett e-mail címét + EmptyEmail = Az e-mail cím nem lehet üres. Kérjük, adjon meg egy érvényes e-mail címet. + InvalidEmail = A(z) '{0}' nem érvényes e-mail cím. Kérjük, adjon meg egy érvényes e-mail címet. + AnotherRecipient = Szeretne megadni egy másik címzettet? (y/N) + MailBodyPrompt = Adja meg az e-mail üzenet törzsének tartalmát + MailBody = As Built Report csatolva +'@ + +# Report Configuration +ReportConfig = ConvertFrom-StringData @' + BannerTitle = As Built Report Konfiguráció + ReportConfigFolder = Adja meg a jelentésmodul konfigurációs fájlok és egyéni stílusszkriptek tárolásához használandó mappa teljes elérési útját [{0}] + OverwriteReportConfig = A megadott mappában már létezik egy jelentésmodul konfigurációs fájl a(z) {0} számára. Szeretné felülírni? (y/N) + CopyFile = '{0}' másolása ide: '{1}'. + OverwriteFile = '{0}' másolása ide: '{1}'. Meglévő fájl felülírása. + SaveAsBuiltConfig = Szeretné menteni az As Built Report mag modul konfigurációs fájlt? (Y/n) + AsBuiltName = Adjon meg egy nevet az As Built Report konfigurációs fájlhoz [AsBuiltReport] + AsBuiltExportPath = Adja meg az As Built Report konfigurációs fájl mentési útvonalát [{0}] + ConfigFolder = As Built Report konfigurációs mappa '{0}' létrehozása. + SaveConfig = As Built Report konfigurációs fájl '{0}.json' mentése az '{1}' útvonalra. + NotSaved = Az As Built Report konfigurációs fájl nem lett mentve. +'@ +} diff --git a/AsBuiltReport.Core/Language/hu-HU/New-AsBuiltReport.psd1 b/AsBuiltReport.Core/Language/hu-HU/New-AsBuiltReport.psd1 new file mode 100644 index 0000000..cb0ef91 --- /dev/null +++ b/AsBuiltReport.Core/Language/hu-HU/New-AsBuiltReport.psd1 @@ -0,0 +1,40 @@ +# culture = 'hu-HU' +ConvertFrom-StringData @' + PwshISE = Az AsBuiltReport nem futtatható a Windows PowerShell ISE-ből. Kérjük, használjon PowerShell parancsablakot. + Password = Jelszó a(z) {0} felhasználóhoz + OutputFolderPath = Az OutputFolderPath '{0}' nem érvényes mappa elérési út. + LoadConfig = As Built Report konfiguráció betöltése innen: {0}. + NoConfigFound = Nem található As Built Report konfiguráció a(z) '{0}' elérési útvonalon. + GeneratingReport = Új As Built Report konfiguráció generálása. + StyleScriptNotFound = Nem található jelentésstílus-szkript a(z) '{0}' elérési útvonalon. + ReportModuleNotFound = Nem található {0} jelentéskonfigurációs fájl a(z) '{1}' elérési útvonalon. + LoadingReportConfig = {0} jelentéskonfigurációs fájl betöltése a(z) '{1}' elérési útról. + ReportConfigNotFound = A jelentéskonfiguráció nem található a(z) '{0}' modul elérési útvonalon. + SetReportFileName = Jelentésfájl neve beállítva: '{0}'. + EmailBannerTitle = E-mail szerver hitelesítő adatok + EmailCredentials = Kérjük, adja meg a hitelesítő adatokat a következőhöz: {0}. + InstalledModule = Az AsBuiltReport.Core {0} jelenleg telepítve van. + AvailableModule = Az AsBuiltReport.Core {0} elérhető. + UpdateModule = Futtassa az 'Update-Module -Name AsBuiltReport.Core -Force' parancsot a legújabb verzió telepítéséhez. + ReportGenerating = Kérjük, várjon, amíg a(z) {0} As Built Report generálódik. + ReportInitializing = > Jelentési keretrendszer inicializálása... + DocumentStyle = > Dokumentumstílus betöltése... + TargetSystem = > Csatlakozás a célrendszerhez és adatok gyűjtése... + ExecutionFailed = A jelentésmodul végrehajtása sikertelen: {0} + BuildingDocument = > Dokumentumstruktúra építése... + ExportingDocument = > Dokumentum exportálása... + Failed = [SIKERTELEN] Jelentésgenerálás sikertelen + ReportStyleScript = Jelentésstílus-szkript végrehajtása a(z) '{0}' elérési útról. + InteractiveAuth = Az interaktív hitelesítés engedélyezve van. Kérjük, ellenőrizze a hitelesítési ablakokat a célrendszerbe való hitelesítéshez. + OutputFolder = {0} As Built Report '{1}' mentve ide: '{2}'. + ReportModuleInfo1 = Dokumentáció: https://github.com/AsBuiltReport/AsBuiltReport.{0} + ReportModuleInfo2 = Problémák vagy hibajelentés: https://github.com/AsBuiltReport/AsBuiltReport.{0}/issues + ReportModuleInfo3 = Ne felejtse el frissíteni a jelentéskonfigurációs fájlt minden új verzió kiadása után: https://www.asbuiltreport.com/user-guide/new-asbuiltreportconfig/ + ProjectWebsite = További részletes információkért tekintse meg az AsBuiltReport projekt webhelyét: https://www.asbuiltreport.com + CommunityProject = Az AsBuiltReport egy közösség által karbantartott nyílt forráskódú projekt. Nincs szponzorálása, támogatása vagy kapcsolata semmilyen technológiai szállítóval, azok alkalmazottaival vagy társult vállalkozásaival. + ReportModuleInstalled = {0} {1} jelenleg telepítve van. + ReportModuleAvailable = {0} {1} elérhető. + ReportModuleUpdate = Futtassa az 'Update-Module -Name {0} -Force' parancsot a legújabb verzió telepítéséhez. + RequiredModuleNotInstalled = {0} {1} vagy újabb verzió szükséges. Futtassa az 'Install-Module -Name {0} -RequiredVersion {1} -AllowClobber' parancsot a szükséges modul telepítéséhez. + RequiredModuleTooOld = {0} {1} jelenleg telepítve van. {0} {2} vagy újabb verzió szükséges. Futtassa az 'Update-Module -Name {0} -RequiredVersion {2} -Force' parancsot a szükséges verzióra való frissítéshez. +'@ diff --git a/AsBuiltReport.Core/Language/hu-HU/New-AsBuiltReportConfig.psd1 b/AsBuiltReport.Core/Language/hu-HU/New-AsBuiltReportConfig.psd1 new file mode 100644 index 0000000..25c9db4 --- /dev/null +++ b/AsBuiltReport.Core/Language/hu-HU/New-AsBuiltReportConfig.psd1 @@ -0,0 +1,11 @@ +# culture = 'hu-HU' +ConvertFrom-StringData @' + FolderNotExist = A(z) '{0}' mappa nem létezik. Kérjük, hozza létre a mappát és futtassa újra a New-AsBuiltReportConfig parancsot. + ProcessConfig = {0} jelentés konfigurációs fájl feldolgozása a(z) {1} modulból, {2} verzió. + CopyConfig = Jelentés konfigurációs fájl '{0}' másolása ide: '{1}'. + CopyModuleConfig = {0} jelentés konfigurációs fájl '{1}' másolása ide: '{2}'. + CreateConfig = {0} jelentés konfigurációs fájl '{1}.json' létrehozva itt: '{2}'. + OverWriteConfig = Jelentés konfigurációs fájl '{0}' másolása ide: '{1}'. Meglévő fájl felülírása. + ForceOverwrite = A(z) {0} jelentés konfigurációs fájl '{1}.json' már létezik itt: '{2}'. Használja a '-Force' paramétert a meglévő fájl felülírásához. + ConfigNotFound = Jelentés konfigurációs fájl nem található a(z) '{0}' modul elérési útjában. +'@ diff --git a/AsBuiltReport.Core/Language/it-IT/AsBuiltReportCoreStyle.psd1 b/AsBuiltReport.Core/Language/it-IT/AsBuiltReportCoreStyle.psd1 new file mode 100644 index 0000000..3237217 --- /dev/null +++ b/AsBuiltReport.Core/Language/it-IT/AsBuiltReportCoreStyle.psd1 @@ -0,0 +1,11 @@ +# culture = 'it-IT' +ConvertFrom-StringData @' + Footer = Pagina + Logo = Logo AsBuiltReport + CoverPageWarning = Impossibile visualizzare l'immagine della copertina. Si prega di impostare 'ShowCoverPageImage' su 'false' nel file di configurazione JSON del report per evitare questo errore. + CoverPage = Copertina + Author = Autore: + Date = Data: + Version = Versione: + TOC = Indice +'@ diff --git a/AsBuiltReport.Core/Language/it-IT/New-AsBuiltConfig.psd1 b/AsBuiltReport.Core/Language/it-IT/New-AsBuiltConfig.psd1 new file mode 100644 index 0000000..3a7ab0b --- /dev/null +++ b/AsBuiltReport.Core/Language/it-IT/New-AsBuiltConfig.psd1 @@ -0,0 +1,58 @@ +# culture = 'it-IT' +@{ + +# As Built Report Information +ReportInfo = ConvertFrom-StringData @' + BannerTitle = Informazioni As Built Report + ReportAuthor = Inserire il nome dell'autore per questo As Built Report [{0}] +'@ + +# Company Configuration +CompanyConfig = ConvertFrom-StringData @' + BannerTitle = Informazioni Aziendali + CompanyInfo = Si desidera inserire le informazioni aziendali per l'As Built Report? (y/N) + CompanyFullName = Inserire il Nome Completo dell'Azienda + CompanyShortName = Inserire il Nome Abbreviato dell'Azienda + CompanyContact = Inserire il Contatto Aziendale + CompanyEmail = Inserire l'Indirizzo Email Aziendale + CompanyPhone = Inserire il Numero di Telefono Aziendale + CompanyAddress = Inserire l'Indirizzo Aziendale +'@ + +# Email Configuration +EmailConfig = ConvertFrom-StringData @' + BannerTitle = Configurazione Email + ConfigureMailSettings = Si desidera inserire la configurazione SMTP? (y/N) + MailServer = Inserire l'FQDN / indirizzo IP del server di posta + EmptyMailServerAddress = L'indirizzo del server di posta non può essere vuoto. Inserire un FQDN / indirizzo IP valido del server di posta. + InvalidMailServer = '{0}' non è un FQDN o indirizzo IP valido. Inserire un FQDN / indirizzo IP valido del server di posta. + MailServerPort587 = Inserire il numero di porta del server di posta [587] + InvalidMailServerPort587 = Numero di porta non valido. Inserire un numero compreso tra 1 e 65535 o premere Invio per il valore predefinito [587]. + MailServerPort25 = Inserire il numero di porta del server di posta [25] + InvalidMailServerPort25 = Numero di porta non valido. Inserire un numero compreso tra 1 e 65535 o premere Invio per il valore predefinito [25]. + MailServerUseSSL = Utilizzare SSL per la connessione al server di posta? (y/N) + MailCredentials = Richiesta autenticazione al server di posta? (y/N) + MailFrom = Inserire l'indirizzo email del mittente + MailTo = Inserire l'indirizzo email del destinatario + EmptyEmail = L'indirizzo email non può essere vuoto. Inserire un indirizzo email valido. + InvalidEmail = '{0}' non è un indirizzo email valido. Inserire un indirizzo email valido. + AnotherRecipient = Si desidera inserire un altro destinatario? (y/N) + MailBodyPrompt = Inserire il contenuto del corpo del messaggio email + MailBody = As Built Report allegato +'@ + +# Report Configuration +ReportConfig = ConvertFrom-StringData @' + BannerTitle = Configurazione As Built Report + ReportConfigFolder = Inserire il percorso completo della cartella da utilizzare per l'archiviazione dei file di configurazione del modulo report e degli script di stile personalizzati [{0}] + OverwriteReportConfig = Un file di configurazione del modulo report per {0} esiste già nella cartella specificata. Si desidera sovrascriverlo? (y/N) + CopyFile = Copia di '{0}' in '{1}'. + OverwriteFile = Copia di '{0}' in '{1}'. Sovrascrittura del file esistente. + SaveAsBuiltConfig = Si desidera salvare il file di configurazione del modulo core di As Built Report? (Y/n) + AsBuiltName = Inserire un nome per il file di configurazione As Built Report [AsBuiltReport] + AsBuiltExportPath = Inserire il percorso per salvare il file di configurazione As Built Report [{0}] + ConfigFolder = Creazione della cartella di configurazione As Built Report '{0}'. + SaveConfig = Salvataggio del file di configurazione As Built Report '{0}.json' nel percorso '{1}'. + NotSaved = File di configurazione As Built Report non salvato. +'@ +} diff --git a/AsBuiltReport.Core/Language/it-IT/New-AsBuiltReport.psd1 b/AsBuiltReport.Core/Language/it-IT/New-AsBuiltReport.psd1 new file mode 100644 index 0000000..2c3cde9 --- /dev/null +++ b/AsBuiltReport.Core/Language/it-IT/New-AsBuiltReport.psd1 @@ -0,0 +1,40 @@ +# culture = 'it-IT' +ConvertFrom-StringData @' + PwshISE = AsBuiltReport non può essere eseguito da Windows PowerShell ISE. Si prega di utilizzare una finestra di comando di PowerShell. + Password = Password per l'utente {0} + OutputFolderPath = OutputFolderPath '{0}' non è un percorso di cartella valido. + LoadConfig = Caricamento configurazione As Built Report da {0}. + NoConfigFound = Impossibile trovare la configurazione As Built Report nel percorso '{0}'. + GeneratingReport = Generazione di una nuova configurazione As Built Report. + StyleScriptNotFound = Impossibile trovare lo script di stile del report nel percorso '{0}'. + ReportModuleNotFound = Impossibile trovare il file di configurazione del report {0} nel percorso '{1}'. + LoadingReportConfig = Caricamento del file di configurazione del report {0} dal percorso '{1}'. + ReportConfigNotFound = Configurazione del report non trovata nel percorso del modulo '{0}'. + SetReportFileName = Impostazione del nome del file del report su '{0}'. + EmailBannerTitle = Credenziali del server email + EmailCredentials = Inserisci le credenziali per {0}. + InstalledModule = AsBuiltReport.Core {0} è attualmente installato. + AvailableModule = AsBuiltReport.Core {0} è disponibile. + UpdateModule = Eseguire 'Update-Module -Name AsBuiltReport.Core -Force' per installare l'ultima versione. + ReportGenerating = Attendere mentre viene generato il report {0} As Built. + ReportInitializing = > Inizializzazione del framework del report... + DocumentStyle = > Caricamento dello stile del documento... + TargetSystem = > Connessione al sistema di destinazione e raccolta dati... + ExecutionFailed = Esecuzione del modulo del report non riuscita: {0} + BuildingDocument = > Creazione della struttura del documento... + ExportingDocument = > Esportazione del documento... + Failed = [NON RIUSCITO] Generazione del report non riuscita + ReportStyleScript = Esecuzione dello script di stile del report dal percorso '{0}'. + InteractiveAuth = L'autenticazione interattiva è abilitata. Controllare le finestre di autenticazione per autenticarsi al sistema di destinazione. + OutputFolder = {0} As Built Report '{1}' è stato salvato in '{2}'. + ReportModuleInfo1 = Documentazione: https://github.com/AsBuiltReport/AsBuiltReport.{0} + ReportModuleInfo2 = Problemi o segnalazione di bug: https://github.com/AsBuiltReport/AsBuiltReport.{0}/issues + ReportModuleInfo3 = Non dimenticare di aggiornare il file di configurazione del report dopo ogni nuova versione: https://www.asbuiltreport.com/user-guide/new-asbuiltreportconfig/ + ProjectWebsite = Si prega di consultare il sito web del progetto AsBuiltReport per informazioni più dettagliate: https://www.asbuiltreport.com + CommunityProject = AsBuiltReport è un progetto open source mantenuto dalla comunità. Non ha sponsorizzazioni, supporto o affiliazione con fornitori di tecnologia, i loro dipendenti o affiliati. + ReportModuleInstalled = {0} {1} è attualmente installato. + ReportModuleAvailable = {0} {1} è disponibile. + ReportModuleUpdate = Eseguire 'Update-Module -Name {0} -Force' per installare l'ultima versione. + RequiredModuleNotInstalled = {0} {1} o superiore è richiesto. Eseguire 'Install-Module -Name {0} -RequiredVersion {1} -AllowClobber' per installare il modulo richiesto. + RequiredModuleTooOld = {0} {1} è attualmente installato. {0} {2} o superiore è richiesto. Eseguire 'Update-Module -Name {0} -RequiredVersion {2} -Force' per aggiornare alla versione richiesta. +'@ diff --git a/AsBuiltReport.Core/Language/it-IT/New-AsBuiltReportConfig.psd1 b/AsBuiltReport.Core/Language/it-IT/New-AsBuiltReportConfig.psd1 new file mode 100644 index 0000000..73596ca --- /dev/null +++ b/AsBuiltReport.Core/Language/it-IT/New-AsBuiltReportConfig.psd1 @@ -0,0 +1,11 @@ +# culture = 'it-IT' +ConvertFrom-StringData @' + FolderNotExist = La cartella '{0}' non esiste. Creare la cartella ed eseguire nuovamente New-AsBuiltReportConfig. + ProcessConfig = Elaborazione del file di configurazione del report {0} dal modulo {1}, versione {2}. + CopyConfig = Copia del file di configurazione del report '{0}' in '{1}'. + CopyModuleConfig = Copia del file di configurazione del report {0} '{1}' in '{2}'. + CreateConfig = File di configurazione del report {0} '{1}.json' creato in '{2}'. + OverWriteConfig = Copia del file di configurazione del report '{0}' in '{1}'. Sovrascrittura del file esistente. + ForceOverwrite = Il file di configurazione del report {0} '{1}.json' esiste già in '{2}'. Utilizzare '-Force' per sovrascrivere il file esistente. + ConfigNotFound = File di configurazione del report non trovato nel percorso del modulo '{0}'. +'@ diff --git a/AsBuiltReport.Core/Language/ja-JP/AsBuiltReportCoreStyle.psd1 b/AsBuiltReport.Core/Language/ja-JP/AsBuiltReportCoreStyle.psd1 new file mode 100644 index 0000000..6ca7df9 --- /dev/null +++ b/AsBuiltReport.Core/Language/ja-JP/AsBuiltReportCoreStyle.psd1 @@ -0,0 +1,11 @@ +# culture = 'ja-JP' +ConvertFrom-StringData @' + Footer = ページ + Logo = AsBuiltReport ロゴ + CoverPageWarning = カバーページの画像を表示できません。このエラーを回避するには、レポートJSON設定ファイルで'ShowCoverPageImage'を'false'に設定してください。 + CoverPage = カバーページ + Author = 著者: + Date = 日付: + Version = バージョン: + TOC = 目次 +'@ diff --git a/AsBuiltReport.Core/Language/ja-JP/New-AsBuiltConfig.psd1 b/AsBuiltReport.Core/Language/ja-JP/New-AsBuiltConfig.psd1 new file mode 100644 index 0000000..10600fe --- /dev/null +++ b/AsBuiltReport.Core/Language/ja-JP/New-AsBuiltConfig.psd1 @@ -0,0 +1,58 @@ +# culture = 'ja-JP' +@{ + +# As Built Report Information +ReportInfo = ConvertFrom-StringData @' + BannerTitle = As Built Report 情報 + ReportAuthor = この As Built Report の作成者名を入力してください [{0}] +'@ + +# Company Configuration +CompanyConfig = ConvertFrom-StringData @' + BannerTitle = 会社情報 + CompanyInfo = As Built Report の会社情報を入力しますか? (y/N) + CompanyFullName = 会社の正式名称を入力してください + CompanyShortName = 会社の略称を入力してください + CompanyContact = 会社の連絡先を入力してください + CompanyEmail = 会社のメールアドレスを入力してください + CompanyPhone = 会社の電話番号を入力してください + CompanyAddress = 会社の住所を入力してください +'@ + +# Email Configuration +EmailConfig = ConvertFrom-StringData @' + BannerTitle = メール設定 + ConfigureMailSettings = SMTP設定を入力しますか? (y/N) + MailServer = メールサーバーのFQDN / IPアドレスを入力してください + EmptyMailServerAddress = メールサーバーのアドレスは空にできません。有効なメールサーバーのFQDN / IPアドレスを入力してください。 + InvalidMailServer = '{0}' は有効なFQDNまたはIPアドレスではありません。有効なメールサーバーのFQDN / IPアドレスを入力してください。 + MailServerPort587 = メールサーバーのポート番号を入力してください [587] + InvalidMailServerPort587 = 無効なポート番号です。1から65535の間の数値を入力するか、デフォルト [587] の場合はEnterキーを押してください。 + MailServerPort25 = メールサーバーのポート番号を入力してください [25] + InvalidMailServerPort25 = 無効なポート番号です。1から65535の間の数値を入力するか、デフォルト [25] の場合はEnterキーを押してください。 + MailServerUseSSL = メールサーバー接続にSSLを使用しますか? (y/N) + MailCredentials = メールサーバーの認証が必要ですか? (y/N) + MailFrom = 送信者のメールアドレスを入力してください + MailTo = 受信者のメールアドレスを入力してください + EmptyEmail = メールアドレスは空にできません。有効なメールアドレスを入力してください。 + InvalidEmail = '{0}' は有効なメールアドレスではありません。有効なメールアドレスを入力してください。 + AnotherRecipient = 別の受信者を入力しますか? (y/N) + MailBodyPrompt = メールメッセージの本文内容を入力してください + MailBody = As Built Report を添付 +'@ + +# Report Configuration +ReportConfig = ConvertFrom-StringData @' + BannerTitle = As Built Report 設定 + ReportConfigFolder = レポートモジュール設定ファイルとカスタムスタイルスクリプトを保存するフォルダの完全パスを入力してください [{0}] + OverwriteReportConfig = 指定されたフォルダに {0} のレポートモジュール設定ファイルが既に存在します。上書きしますか? (y/N) + CopyFile = '{0}' を '{1}' にコピーしています。 + OverwriteFile = '{0}' を '{1}' にコピーしています。既存のファイルを上書きします。 + SaveAsBuiltConfig = As Built Report コアモジュール設定ファイルを保存しますか? (Y/n) + AsBuiltName = As Built Report 設定ファイルの名前を入力してください [AsBuiltReport] + AsBuiltExportPath = As Built Report 設定ファイルを保存するパスを入力してください [{0}] + ConfigFolder = As Built Report 設定フォルダ '{0}' を作成しています。 + SaveConfig = As Built Report 設定ファイル '{0}.json' をパス '{1}' に保存しています。 + NotSaved = As Built Report 設定ファイルは保存されませんでした。 +'@ +} diff --git a/AsBuiltReport.Core/Language/ja-JP/New-AsBuiltReport.psd1 b/AsBuiltReport.Core/Language/ja-JP/New-AsBuiltReport.psd1 new file mode 100644 index 0000000..e8ed52c --- /dev/null +++ b/AsBuiltReport.Core/Language/ja-JP/New-AsBuiltReport.psd1 @@ -0,0 +1,40 @@ +# culture = 'ja-JP' +ConvertFrom-StringData @' + PwshISE = AsBuiltReportはWindows PowerShell ISEから実行できません。PowerShellコマンドウィンドウを使用してください。 + Password = ユーザー {0} のパスワード + OutputFolderPath = OutputFolderPath '{0}' は有効なフォルダパスではありません。 + LoadConfig = {0} からAs Built Report設定を読み込んでいます。 + NoConfigFound = パス '{0}' でAs Built Report設定が見つかりませんでした。 + GeneratingReport = 新しいAs Built Report設定を生成しています。 + StyleScriptNotFound = パス '{0}' でレポートスタイルスクリプトが見つかりませんでした。 + ReportModuleNotFound = パス '{1}' で {0} レポート設定ファイルが見つかりませんでした。 + LoadingReportConfig = パス '{1}' から {0} レポート設定ファイルを読み込んでいます。 + ReportConfigNotFound = モジュールパス '{0}' でレポート設定が見つかりませんでした。 + SetReportFileName = レポートファイル名を '{0}' に設定しています。 + EmailBannerTitle = メールサーバー資格情報 + EmailCredentials = {0} の資格情報を入力してください。 + InstalledModule = AsBuiltReport.Core {0} は現在インストールされています。 + AvailableModule = AsBuiltReport.Core {0} が利用可能です。 + UpdateModule = 最新バージョンをインストールするには 'Update-Module -Name AsBuiltReport.Core -Force' を実行してください。 + ReportGenerating = {0} As Built Reportを生成しています。しばらくお待ちください。 + ReportInitializing = > レポートフレームワークを初期化しています... + DocumentStyle = > ドキュメントスタイルを読み込んでいます... + TargetSystem = > ターゲットシステムに接続してデータを収集しています... + ExecutionFailed = レポートモジュールの実行に失敗しました: {0} + BuildingDocument = > ドキュメント構造を構築しています... + ExportingDocument = > ドキュメントをエクスポートしています... + Failed = [失敗] レポート生成に失敗しました + ReportStyleScript = パス '{0}' からレポートスタイルスクリプトを実行しています。 + InteractiveAuth = 対話型認証が有効になっています。ターゲットシステムへの認証を行うには、認証ウィンドウを確認してください。 + OutputFolder = {0} As Built Report '{1}' は '{2}' に保存されました。 + ReportModuleInfo1 = ドキュメント: https://github.com/AsBuiltReport/AsBuiltReport.{0} + ReportModuleInfo2 = 問題またはバグ報告: https://github.com/AsBuiltReport/AsBuiltReport.{0}/issues + ReportModuleInfo3 = 新しいバージョンリリース後は、レポート設定ファイルを更新することを忘れないでください: https://www.asbuiltreport.com/user-guide/new-asbuiltreportconfig/ + ProjectWebsite = 詳細については、AsBuiltReportプロジェクトのWebサイトを参照してください: https://www.asbuiltreport.com + CommunityProject = AsBuiltReportは、コミュニティが保守するオープンソースプロジェクトです。いかなるテクノロジーベンダー、その従業員、または関連会社とのスポンサーシップ、支援、または提携はありません。 + ReportModuleInstalled = {0} {1} は現在インストールされています。 + ReportModuleAvailable = {0} {1} が利用可能です。 + ReportModuleUpdate = 最新バージョンをインストールするには 'Update-Module -Name {0} -Force' を実行してください。 + RequiredModuleNotInstalled = {0} {1} 以降が必要です。必要なモジュールをインストールするには 'Install-Module -Name {0} -RequiredVersion {1} -AllowClobber' を実行してください。 + RequiredModuleTooOld = {0} {1} は現在インストールされています。{0} {2} 以降が必要です。必要なバージョンに更新するには 'Update-Module -Name {0} -RequiredVersion {2} -Force' を実行してください。 +'@ diff --git a/AsBuiltReport.Core/Language/ja-JP/New-AsBuiltReportConfig.psd1 b/AsBuiltReport.Core/Language/ja-JP/New-AsBuiltReportConfig.psd1 new file mode 100644 index 0000000..679fb91 --- /dev/null +++ b/AsBuiltReport.Core/Language/ja-JP/New-AsBuiltReportConfig.psd1 @@ -0,0 +1,11 @@ +# culture = 'ja-JP' +ConvertFrom-StringData @' + FolderNotExist = フォルダ '{0}' は存在しません。フォルダを作成して、New-AsBuiltReportConfig を再度実行してください。 + ProcessConfig = モジュール {1} バージョン {2} から {0} レポート設定ファイルを処理しています。 + CopyConfig = レポート設定ファイル '{0}' を '{1}' にコピーしています。 + CopyModuleConfig = {0} レポート設定ファイル '{1}' を '{2}' にコピーしています。 + CreateConfig = {0} レポート設定ファイル '{1}.json' が '{2}' に作成されました。 + OverWriteConfig = レポート設定ファイル '{0}' を '{1}' にコピーしています。既存のファイルを上書きします。 + ForceOverwrite = {0} レポート設定ファイル '{1}.json' は既に '{2}' に存在します。既存のファイルを上書きするには '-Force' を使用してください。 + ConfigNotFound = モジュールパス '{0}' にレポート設定ファイルが見つかりません。 +'@ diff --git a/AsBuiltReport.Core/Language/ko-KR/AsBuiltReportCoreStyle.psd1 b/AsBuiltReport.Core/Language/ko-KR/AsBuiltReportCoreStyle.psd1 new file mode 100644 index 0000000..a4df8af --- /dev/null +++ b/AsBuiltReport.Core/Language/ko-KR/AsBuiltReportCoreStyle.psd1 @@ -0,0 +1,11 @@ +# culture = 'ko-KR' +ConvertFrom-StringData @' + Footer = 페이지 + Logo = AsBuiltReport 로고 + CoverPageWarning = 표지 이미지를 표시할 수 없습니다. 이 오류를 방지하려면 보고서 JSON 구성 파일에서 'ShowCoverPageImage'를 'false'로 설정하십시오. + CoverPage = 표지 + Author = 저자: + Date = 날짜: + Version = 버전: + TOC = 목차 +'@ diff --git a/AsBuiltReport.Core/Language/ko-KR/New-AsBuiltConfig.psd1 b/AsBuiltReport.Core/Language/ko-KR/New-AsBuiltConfig.psd1 new file mode 100644 index 0000000..22a14e1 --- /dev/null +++ b/AsBuiltReport.Core/Language/ko-KR/New-AsBuiltConfig.psd1 @@ -0,0 +1,58 @@ +# culture = 'ko-KR' +@{ + +# As Built Report Information +ReportInfo = ConvertFrom-StringData @' + BannerTitle = As Built Report 정보 + ReportAuthor = 이 As Built Report의 작성자 이름을 입력하십시오 [{0}] +'@ + +# Company Configuration +CompanyConfig = ConvertFrom-StringData @' + BannerTitle = 회사 정보 + CompanyInfo = As Built Report에 대한 회사 정보를 입력하시겠습니까? (y/N) + CompanyFullName = 회사 전체 이름을 입력하십시오 + CompanyShortName = 회사 약칭을 입력하십시오 + CompanyContact = 회사 연락처를 입력하십시오 + CompanyEmail = 회사 이메일 주소를 입력하십시오 + CompanyPhone = 회사 전화번호를 입력하십시오 + CompanyAddress = 회사 주소를 입력하십시오 +'@ + +# Email Configuration +EmailConfig = ConvertFrom-StringData @' + BannerTitle = 이메일 구성 + ConfigureMailSettings = SMTP 구성을 입력하시겠습니까? (y/N) + MailServer = 메일 서버 FQDN / IP 주소를 입력하십시오 + EmptyMailServerAddress = 메일 서버 주소는 비워둘 수 없습니다. 유효한 메일 서버 FQDN / IP 주소를 입력하십시오. + InvalidMailServer = '{0}'은(는) 유효한 FQDN 또는 IP 주소가 아닙니다. 유효한 메일 서버 FQDN / IP 주소를 입력하십시오. + MailServerPort587 = 메일 서버 포트 번호를 입력하십시오 [587] + InvalidMailServerPort587 = 잘못된 포트 번호입니다. 1에서 65535 사이의 숫자를 입력하거나 기본값 [587]을 사용하려면 Enter를 누르십시오. + MailServerPort25 = 메일 서버 포트 번호를 입력하십시오 [25] + InvalidMailServerPort25 = 잘못된 포트 번호입니다. 1에서 65535 사이의 숫자를 입력하거나 기본값 [25]을 사용하려면 Enter를 누르십시오. + MailServerUseSSL = 메일 서버 연결에 SSL을 사용하시겠습니까? (y/N) + MailCredentials = 메일 서버 인증이 필요합니까? (y/N) + MailFrom = 보내는 사람 이메일 주소를 입력하십시오 + MailTo = 받는 사람 이메일 주소를 입력하십시오 + EmptyEmail = 이메일 주소는 비워둘 수 없습니다. 유효한 이메일 주소를 입력하십시오. + InvalidEmail = '{0}'은(는) 유효한 이메일 주소가 아닙니다. 유효한 이메일 주소를 입력하십시오. + AnotherRecipient = 다른 받는 사람을 입력하시겠습니까? (y/N) + MailBodyPrompt = 이메일 메시지 본문 내용을 입력하십시오 + MailBody = As Built Report 첨부됨 +'@ + +# Report Configuration +ReportConfig = ConvertFrom-StringData @' + BannerTitle = As Built Report 구성 + ReportConfigFolder = 보고서 모듈 구성 파일 및 사용자 지정 스타일 스크립트를 저장하는 데 사용할 폴더의 전체 경로를 입력하십시오 [{0}] + OverwriteReportConfig = 지정된 폴더에 {0}에 대한 보고서 모듈 구성 파일이 이미 있습니다. 덮어쓰시겠습니까? (y/N) + CopyFile = '{0}'을(를) '{1}'(으)로 복사하는 중입니다. + OverwriteFile = '{0}'을(를) '{1}'(으)로 복사하는 중입니다. 기존 파일을 덮어씁니다. + SaveAsBuiltConfig = As Built Report 핵심 모듈 구성 파일을 저장하시겠습니까? (Y/n) + AsBuiltName = As Built Report 구성 파일의 이름을 입력하십시오 [AsBuiltReport] + AsBuiltExportPath = As Built Report 구성 파일을 저장할 경로를 입력하십시오 [{0}] + ConfigFolder = As Built Report 구성 폴더 '{0}'을(를) 만드는 중입니다. + SaveConfig = As Built Report 구성 파일 '{0}.json'을(를) 경로 '{1}'에 저장하는 중입니다. + NotSaved = As Built Report 구성 파일이 저장되지 않았습니다. +'@ +} diff --git a/AsBuiltReport.Core/Language/ko-KR/New-AsBuiltReport.psd1 b/AsBuiltReport.Core/Language/ko-KR/New-AsBuiltReport.psd1 new file mode 100644 index 0000000..daaab3f --- /dev/null +++ b/AsBuiltReport.Core/Language/ko-KR/New-AsBuiltReport.psd1 @@ -0,0 +1,40 @@ +# culture = 'ko-KR' +ConvertFrom-StringData @' + PwshISE = AsBuiltReport는 Windows PowerShell ISE에서 실행할 수 없습니다. PowerShell 명령 창을 사용하십시오. + Password = 사용자 {0}의 암호 + OutputFolderPath = OutputFolderPath '{0}'은(는) 유효한 폴더 경로가 아닙니다. + LoadConfig = {0}에서 As Built Report 구성을 로드하는 중입니다. + NoConfigFound = 경로 '{0}'에서 As Built Report 구성을 찾을 수 없습니다. + GeneratingReport = 새 As Built Report 구성을 생성하는 중입니다. + StyleScriptNotFound = 경로 '{0}'에서 보고서 스타일 스크립트를 찾을 수 없습니다. + ReportModuleNotFound = 경로 '{1}'에서 {0} 보고서 구성 파일을 찾을 수 없습니다. + LoadingReportConfig = 경로 '{1}'에서 {0} 보고서 구성 파일을 로드하는 중입니다. + ReportConfigNotFound = 모듈 경로 '{0}'에서 보고서 구성을 찾을 수 없습니다. + SetReportFileName = 보고서 파일 이름을 '{0}'(으)로 설정하는 중입니다. + EmailBannerTitle = 이메일 서버 자격 증명 + EmailCredentials = {0}에 대한 자격 증명을 입력하십시오. + InstalledModule = AsBuiltReport.Core {0}이(가) 현재 설치되어 있습니다. + AvailableModule = AsBuiltReport.Core {0}을(를) 사용할 수 있습니다. + UpdateModule = 최신 버전을 설치하려면 'Update-Module -Name AsBuiltReport.Core -Force'를 실행하십시오. + ReportGenerating = {0} As Built Report가 생성되는 동안 기다려 주십시오. + ReportInitializing = > 보고서 프레임워크를 초기화하는 중... + DocumentStyle = > 문서 스타일을 로드하는 중... + TargetSystem = > 대상 시스템에 연결하고 데이터를 수집하는 중... + ExecutionFailed = 보고서 모듈 실행 실패: {0} + BuildingDocument = > 문서 구조를 구축하는 중... + ExportingDocument = > 문서를 내보내는 중... + Failed = [실패] 보고서 생성 실패 + ReportStyleScript = 경로 '{0}'에서 보고서 스타일 스크립트를 실행하는 중입니다. + InteractiveAuth = 대화형 인증이 활성화되어 있습니다. 대상 시스템에 인증하려면 인증 창을 확인하십시오. + OutputFolder = {0} As Built Report '{1}'이(가) '{2}'에 저장되었습니다. + ReportModuleInfo1 = 문서: https://github.com/AsBuiltReport/AsBuiltReport.{0} + ReportModuleInfo2 = 문제 또는 버그 보고: https://github.com/AsBuiltReport/AsBuiltReport.{0}/issues + ReportModuleInfo3 = 새 버전이 출시된 후 보고서 구성 파일을 업데이트하는 것을 잊지 마십시오: https://www.asbuiltreport.com/user-guide/new-asbuiltreportconfig/ + ProjectWebsite = 자세한 내용은 AsBuiltReport 프로젝트 웹사이트를 참조하십시오: https://www.asbuiltreport.com + CommunityProject = AsBuiltReport는 커뮤니티에서 유지 관리하는 오픈 소스 프로젝트입니다. 기술 공급업체, 직원 또는 계열사와의 후원, 보증 또는 제휴가 없습니다. + ReportModuleInstalled = {0} {1}이(가) 현재 설치되어 있습니다. + ReportModuleAvailable = {0} {1}을(를) 사용할 수 있습니다. + ReportModuleUpdate = 최신 버전을 설치하려면 'Update-Module -Name {0} -Force'를 실행하십시오. + RequiredModuleNotInstalled = {0} {1} 이상이 필요합니다. 필요한 모듈을 설치하려면 'Install-Module -Name {0} -RequiredVersion {1} -AllowClobber'를 실행하십시오. + RequiredModuleTooOld = {0} {1}이(가) 현재 설치되어 있습니다. {0} {2} 이상이 필요합니다. 필요한 버전으로 업데이트하려면 'Update-Module -Name {0} -RequiredVersion {2} -Force'를 실행하십시오. +'@ diff --git a/AsBuiltReport.Core/Language/ko-KR/New-AsBuiltReportConfig.psd1 b/AsBuiltReport.Core/Language/ko-KR/New-AsBuiltReportConfig.psd1 new file mode 100644 index 0000000..d24f009 --- /dev/null +++ b/AsBuiltReport.Core/Language/ko-KR/New-AsBuiltReportConfig.psd1 @@ -0,0 +1,11 @@ +# culture = 'ko-KR' +ConvertFrom-StringData @' + FolderNotExist = 폴더 '{0}'이(가) 존재하지 않습니다. 폴더를 만들고 New-AsBuiltReportConfig를 다시 실행하십시오. + ProcessConfig = 모듈 {1} 버전 {2}에서 {0} 보고서 구성 파일을 처리하는 중입니다. + CopyConfig = 보고서 구성 파일 '{0}'을(를) '{1}'(으)로 복사하는 중입니다. + CopyModuleConfig = {0} 보고서 구성 파일 '{1}'을(를) '{2}'(으)로 복사하는 중입니다. + CreateConfig = {0} 보고서 구성 파일 '{1}.json'이(가) '{2}'에 생성되었습니다. + OverWriteConfig = 보고서 구성 파일 '{0}'을(를) '{1}'(으)로 복사하는 중입니다. 기존 파일을 덮어씁니다. + ForceOverwrite = {0} 보고서 구성 파일 '{1}.json'이(가) '{2}'에 이미 있습니다. 기존 파일을 덮어쓰려면 '-Force'를 사용하십시오. + ConfigNotFound = 모듈 경로 '{0}'에서 보고서 구성 파일을 찾을 수 없습니다. +'@ diff --git a/AsBuiltReport.Core/Language/nb-NO/AsBuiltReportCoreStyle.psd1 b/AsBuiltReport.Core/Language/nb-NO/AsBuiltReportCoreStyle.psd1 new file mode 100644 index 0000000..ab0af02 --- /dev/null +++ b/AsBuiltReport.Core/Language/nb-NO/AsBuiltReportCoreStyle.psd1 @@ -0,0 +1,11 @@ +# culture = 'nb-NO' +ConvertFrom-StringData @' + Footer = Side + Logo = AsBuiltReport Logo + CoverPageWarning = Kan ikke vise forsidebilde. Vennligst sett 'ShowCoverPageImage' til 'false' i rapportens JSON-konfigurasjonsfil for å unngå denne feilen. + CoverPage = Forside + Author = Forfatter: + Date = Dato: + Version = Versjon: + TOC = Innholdsfortegnelse +'@ diff --git a/AsBuiltReport.Core/Language/nb-NO/New-AsBuiltConfig.psd1 b/AsBuiltReport.Core/Language/nb-NO/New-AsBuiltConfig.psd1 new file mode 100644 index 0000000..78c7ceb --- /dev/null +++ b/AsBuiltReport.Core/Language/nb-NO/New-AsBuiltConfig.psd1 @@ -0,0 +1,58 @@ +# culture = 'nb-NO' +@{ + +# As Built Report Information +ReportInfo = ConvertFrom-StringData @' + BannerTitle = As Built Report Informasjon + ReportAuthor = Skriv inn navnet på forfatteren for denne As Built Report [{0}] +'@ + +# Company Configuration +CompanyConfig = ConvertFrom-StringData @' + BannerTitle = Selskapsinformasjon + CompanyInfo = Vil du oppgi selskapsinformasjon for As Built Report? (y/N) + CompanyFullName = Skriv inn det fullstendige selskapsnavnet + CompanyShortName = Skriv inn selskapets kortnavn + CompanyContact = Skriv inn selskapskontakt + CompanyEmail = Skriv inn selskapets e-postadresse + CompanyPhone = Skriv inn selskapets telefonnummer + CompanyAddress = Skriv inn selskapsadressen +'@ + +# Email Configuration +EmailConfig = ConvertFrom-StringData @' + BannerTitle = E-postkonfigurasjon + ConfigureMailSettings = Vil du oppgi SMTP-konfigurasjon? (y/N) + MailServer = Skriv inn e-postserverens FQDN / IP-adresse + EmptyMailServerAddress = E-postserveradressen kan ikke være tom. Vennligst skriv inn en gyldig FQDN / IP-adresse for e-postserveren. + InvalidMailServer = '{0}' er ikke en gyldig FQDN eller IP-adresse. Vennligst skriv inn en gyldig FQDN / IP-adresse for e-postserveren. + MailServerPort587 = Skriv inn e-postserverens portnummer [587] + InvalidMailServerPort587 = Ugyldig portnummer. Vennligst skriv inn et tall mellom 1 og 65535, eller trykk Enter for standardverdi [587]. + MailServerPort25 = Skriv inn e-postserverens portnummer [25] + InvalidMailServerPort25 = Ugyldig portnummer. Vennligst skriv inn et tall mellom 1 og 65535, eller trykk Enter for standardverdi [25]. + MailServerUseSSL = Bruk SSL for e-postservertilkobling? (y/N) + MailCredentials = Krever e-postserveren autentisering? (y/N) + MailFrom = Skriv inn avsenderens e-postadresse + MailTo = Skriv inn mottakerens e-postadresse + EmptyEmail = E-postadressen kan ikke være tom. Vennligst skriv inn en gyldig e-postadresse. + InvalidEmail = '{0}' er ikke en gyldig e-postadresse. Vennligst skriv inn en gyldig e-postadresse. + AnotherRecipient = Vil du oppgi en annen mottaker? (y/N) + MailBodyPrompt = Skriv inn innholdet i e-postmeldingen + MailBody = As Built Report vedlagt +'@ + +# Report Configuration +ReportConfig = ConvertFrom-StringData @' + BannerTitle = As Built Report Konfigurasjon + ReportConfigFolder = Skriv inn hele banen til mappen som skal brukes til å lagre rapportmodulkonfigurasjonsfiler og tilpassede stilskript [{0}] + OverwriteReportConfig = En rapportmodulkonfigurasjonsfil for {0} finnes allerede i den angitte mappen. Vil du overskrive den? (y/N) + CopyFile = Kopierer '{0}' til '{1}'. + OverwriteFile = Kopierer '{0}' til '{1}'. Overskriver eksisterende fil. + SaveAsBuiltConfig = Vil du lagre As Built Report kjernemodul konfigurasjonsfilen? (Y/n) + AsBuiltName = Skriv inn et navn for As Built Report konfigurasjonsfilen [AsBuiltReport] + AsBuiltExportPath = Skriv inn banen for å lagre As Built Report konfigurasjonsfilen [{0}] + ConfigFolder = Oppretter As Built Report konfigurasjonsmappe '{0}'. + SaveConfig = Lagrer As Built Report konfigurasjonsfil '{0}.json' til banen '{1}'. + NotSaved = As Built Report konfigurasjonsfilen ble ikke lagret. +'@ +} diff --git a/AsBuiltReport.Core/Language/nb-NO/New-AsBuiltReport.psd1 b/AsBuiltReport.Core/Language/nb-NO/New-AsBuiltReport.psd1 new file mode 100644 index 0000000..d4d521b --- /dev/null +++ b/AsBuiltReport.Core/Language/nb-NO/New-AsBuiltReport.psd1 @@ -0,0 +1,40 @@ +# culture = 'nb-NO' +ConvertFrom-StringData @' + PwshISE = AsBuiltReport kan ikke kjøres fra Windows PowerShell ISE. Bruk et PowerShell-kommandovindu i stedet. + Password = Passord for bruker {0} + OutputFolderPath = OutputFolderPath '{0}' er ikke en gyldig mappebane. + LoadConfig = Laster As Built Report-konfigurasjon fra {0}. + NoConfigFound = Fant ikke As Built Report-konfigurasjon i banen '{0}'. + GeneratingReport = Genererer ny As Built Report-konfigurasjon. + StyleScriptNotFound = Fant ikke rapportstilskript i banen '{0}'. + ReportModuleNotFound = Fant ikke {0} rapportkonfigurasjonsfil i banen '{1}'. + LoadingReportConfig = Laster {0} rapportkonfigurasjonsfil fra banen '{1}'. + ReportConfigNotFound = Rapportkonfigurasjon ikke funnet i modulbanen '{0}'. + SetReportFileName = Angir rapportfilnavn til '{0}'. + EmailBannerTitle = E-postserverlegitimasjon + EmailCredentials = Vennligst skriv inn legitimasjon for {0}. + InstalledModule = AsBuiltReport.Core {0} er for øyeblikket installert. + AvailableModule = AsBuiltReport.Core {0} er tilgjengelig. + UpdateModule = Kjør 'Update-Module -Name AsBuiltReport.Core -Force' for å installere den nyeste versjonen. + ReportGenerating = Vennligst vent mens {0} As Built Report genereres. + ReportInitializing = > Initialiserer rapportrammeverk... + DocumentStyle = > Laster dokumentstil... + TargetSystem = > Kobler til målsystem og samler data... + ExecutionFailed = Kjøring av rapportmodul mislyktes: {0} + BuildingDocument = > Bygger dokumentstruktur... + ExportingDocument = > Eksporterer dokument... + Failed = [MISLYKTES] Rapportgenerering mislyktes + ReportStyleScript = Kjører rapportstilskript fra banen '{0}'. + InteractiveAuth = Interaktiv autentisering er aktivert. Vennligst sjekk autentiseringsvinduer for å autentisere til målsystemet ditt. + OutputFolder = {0} As Built Report '{1}' har blitt lagret i '{2}'. + ReportModuleInfo1 = Dokumentasjon: https://github.com/AsBuiltReport/AsBuiltReport.{0} + ReportModuleInfo2 = Problemer eller feilrapportering: https://github.com/AsBuiltReport/AsBuiltReport.{0}/issues + ReportModuleInfo3 = Ikke glem å oppdatere rapportkonfigurasjonsfilen etter hver ny versjonsutgivelse: https://www.asbuiltreport.com/user-guide/new-asbuiltreportconfig/ + ProjectWebsite = Vennligst se AsBuiltReport-prosjektets nettsted for mer detaljert informasjon: https://www.asbuiltreport.com + CommunityProject = AsBuiltReport er et fellesskapsdrevet åpen kildekode-prosjekt. Det har ingen sponsing, godkjenning eller tilknytning til noen teknologileverandører, deres ansatte eller tilknyttede selskaper. + ReportModuleInstalled = {0} {1} er for øyeblikket installert. + ReportModuleAvailable = {0} {1} er tilgjengelig. + ReportModuleUpdate = Kjør 'Update-Module -Name {0} -Force' for å installere den nyeste versjonen. + RequiredModuleNotInstalled = {0} {1} eller høyere er påkrevd. Kjør 'Install-Module -Name {0} -RequiredVersion {1} -AllowClobber' for å installere den påkrevde modulen. + RequiredModuleTooOld = {0} {1} er for øyeblikket installert. {0} {2} eller høyere er påkrevd. Kjør 'Update-Module -Name {0} -RequiredVersion {2} -Force' for å oppdatere til påkrevd versjon. +'@ diff --git a/AsBuiltReport.Core/Language/nb-NO/New-AsBuiltReportConfig.psd1 b/AsBuiltReport.Core/Language/nb-NO/New-AsBuiltReportConfig.psd1 new file mode 100644 index 0000000..03f8b56 --- /dev/null +++ b/AsBuiltReport.Core/Language/nb-NO/New-AsBuiltReportConfig.psd1 @@ -0,0 +1,11 @@ +# culture = 'nb-NO' +ConvertFrom-StringData @' + FolderNotExist = Mappen '{0}' finnes ikke. Vennligst opprett mappen og kjør New-AsBuiltReportConfig på nytt. + ProcessConfig = Behandler {0} rapportkonfigurasjonsfil fra modul {1}, versjon {2}. + CopyConfig = Kopierer rapportkonfigurasjonsfil '{0}' til '{1}'. + CopyModuleConfig = Kopierer {0} rapportkonfigurasjonsfil '{1}' til '{2}'. + CreateConfig = {0} rapportkonfigurasjonsfil '{1}.json' opprettet i '{2}'. + OverWriteConfig = Kopierer rapportkonfigurasjonsfil '{0}' til '{1}'. Overskriver eksisterende fil. + ForceOverwrite = {0} rapportkonfigurasjonsfil '{1}.json' finnes allerede i '{2}'. Bruk '-Force' for å overskrive eksisterende fil. + ConfigNotFound = Rapportkonfigurasjonsfil ikke funnet i modulbanen '{0}'. +'@ diff --git a/AsBuiltReport.Core/Language/nl-NL/AsBuiltReportCoreStyle.psd1 b/AsBuiltReport.Core/Language/nl-NL/AsBuiltReportCoreStyle.psd1 new file mode 100644 index 0000000..8e2edf4 --- /dev/null +++ b/AsBuiltReport.Core/Language/nl-NL/AsBuiltReportCoreStyle.psd1 @@ -0,0 +1,11 @@ +# culture = 'nl-NL' +ConvertFrom-StringData @' + Footer = Pagina + Logo = AsBuiltReport Logo + CoverPageWarning = Kan voorpagina-afbeelding niet weergeven. Stel 'ShowCoverPageImage' in op 'false' in het JSON-configuratiebestand van het rapport om deze fout te voorkomen. + CoverPage = Voorpagina + Author = Auteur: + Date = Datum: + Version = Versie: + TOC = Inhoudsopgave +'@ diff --git a/AsBuiltReport.Core/Language/nl-NL/New-AsBuiltConfig.psd1 b/AsBuiltReport.Core/Language/nl-NL/New-AsBuiltConfig.psd1 new file mode 100644 index 0000000..7bbda4e --- /dev/null +++ b/AsBuiltReport.Core/Language/nl-NL/New-AsBuiltConfig.psd1 @@ -0,0 +1,58 @@ +# culture = 'nl-NL' +@{ + +# As Built Report Information +ReportInfo = ConvertFrom-StringData @' + BannerTitle = As Built Report Informatie + ReportAuthor = Voer de naam van de auteur in voor dit As Built Report [{0}] +'@ + +# Company Configuration +CompanyConfig = ConvertFrom-StringData @' + BannerTitle = Bedrijfsinformatie + CompanyInfo = Wilt u bedrijfsinformatie invoeren voor het As Built Report? (y/N) + CompanyFullName = Voer de volledige bedrijfsnaam in + CompanyShortName = Voer de verkorte bedrijfsnaam in + CompanyContact = Voer het bedrijfscontact in + CompanyEmail = Voer het e-mailadres van het bedrijf in + CompanyPhone = Voer het telefoonnummer van het bedrijf in + CompanyAddress = Voer het bedrijfsadres in +'@ + +# Email Configuration +EmailConfig = ConvertFrom-StringData @' + BannerTitle = E-mailconfiguratie + ConfigureMailSettings = Wilt u SMTP-configuratie invoeren? (y/N) + MailServer = Voer de FQDN / het IP-adres van de mailserver in + EmptyMailServerAddress = Het adres van de mailserver mag niet leeg zijn. Voer een geldige FQDN / IP-adres van de mailserver in. + InvalidMailServer = '{0}' is geen geldige FQDN of IP-adres. Voer een geldige FQDN / IP-adres van de mailserver in. + MailServerPort587 = Voer het poortnummer van de mailserver in [587] + InvalidMailServerPort587 = Ongeldig poortnummer. Voer een nummer tussen 1 en 65535 in, of druk op Enter voor de standaardwaarde [587]. + MailServerPort25 = Voer het poortnummer van de mailserver in [25] + InvalidMailServerPort25 = Ongeldig poortnummer. Voer een nummer tussen 1 en 65535 in, of druk op Enter voor de standaardwaarde [25]. + MailServerUseSSL = SSL gebruiken voor mailserververbinding? (y/N) + MailCredentials = Is mailserververificatie vereist? (y/N) + MailFrom = Voer het e-mailadres van de afzender in + MailTo = Voer het e-mailadres van de ontvanger in + EmptyEmail = Het e-mailadres mag niet leeg zijn. Voer een geldig e-mailadres in. + InvalidEmail = '{0}' is geen geldig e-mailadres. Voer een geldig e-mailadres in. + AnotherRecipient = Wilt u een andere ontvanger invoeren? (y/N) + MailBodyPrompt = Voer de inhoud van het e-mailbericht in + MailBody = As Built Report bijgevoegd +'@ + +# Report Configuration +ReportConfig = ConvertFrom-StringData @' + BannerTitle = As Built Report Configuratie + ReportConfigFolder = Voer het volledige pad in van de map die moet worden gebruikt voor het opslaan van configuratiebestanden van de rapportmodule en aangepaste stijlscripts [{0}] + OverwriteReportConfig = Er bestaat al een configuratiebestand van de rapportmodule voor {0} in de opgegeven map. Wilt u deze overschrijven? (y/N) + CopyFile = '{0}' wordt gekopieerd naar '{1}'. + OverwriteFile = '{0}' wordt gekopieerd naar '{1}'. Bestaand bestand wordt overschreven. + SaveAsBuiltConfig = Wilt u het configuratiebestand van de As Built Report-kernmodule opslaan? (Y/n) + AsBuiltName = Voer een naam in voor het As Built Report-configuratiebestand [AsBuiltReport] + AsBuiltExportPath = Voer het pad in om het As Built Report-configuratiebestand op te slaan [{0}] + ConfigFolder = As Built Report-configuratiemap '{0}' wordt gemaakt. + SaveConfig = As Built Report-configuratiebestand '{0}.json' wordt opgeslagen in pad '{1}'. + NotSaved = As Built Report-configuratiebestand niet opgeslagen. +'@ +} diff --git a/AsBuiltReport.Core/Language/nl-NL/New-AsBuiltReport.psd1 b/AsBuiltReport.Core/Language/nl-NL/New-AsBuiltReport.psd1 new file mode 100644 index 0000000..099beef --- /dev/null +++ b/AsBuiltReport.Core/Language/nl-NL/New-AsBuiltReport.psd1 @@ -0,0 +1,40 @@ +# culture = 'nl-NL' +ConvertFrom-StringData @' + PwshISE = AsBuiltReport kan niet worden uitgevoerd vanuit Windows PowerShell ISE. Gebruik in plaats daarvan een PowerShell-opdrachtvenster. + Password = Wachtwoord voor gebruiker {0} + OutputFolderPath = OutputFolderPath '{0}' is geen geldig mappad. + LoadConfig = As Built Report-configuratie laden van {0}. + NoConfigFound = Kan As Built Report-configuratie niet vinden in pad '{0}'. + GeneratingReport = Nieuwe As Built Report-configuratie genereren. + StyleScriptNotFound = Kan rapportstijlscript niet vinden in pad '{0}'. + ReportModuleNotFound = Kan {0} rapportconfiguratiebestand niet vinden in pad '{1}'. + LoadingReportConfig = {0} rapportconfiguratiebestand laden van pad '{1}'. + ReportConfigNotFound = Rapportconfiguratie niet gevonden in modulepad '{0}'. + SetReportFileName = Rapportbestandsnaam instellen op '{0}'. + EmailBannerTitle = E-mailserverreferenties + EmailCredentials = Voer referenties in voor {0}. + InstalledModule = AsBuiltReport.Core {0} is momenteel geïnstalleerd. + AvailableModule = AsBuiltReport.Core {0} is beschikbaar. + UpdateModule = Voer 'Update-Module -Name AsBuiltReport.Core -Force' uit om de nieuwste versie te installeren. + ReportGenerating = Even geduld terwijl het {0} As Built Report wordt gegenereerd. + ReportInitializing = > Rapportframework initialiseren... + DocumentStyle = > Documentstijl laden... + TargetSystem = > Verbinding maken met doelsysteem en gegevens verzamelen... + ExecutionFailed = Uitvoering van rapportmodule mislukt: {0} + BuildingDocument = > Documentstructuur bouwen... + ExportingDocument = > Document exporteren... + Failed = [MISLUKT] Rapportgeneratie mislukt + ReportStyleScript = Rapportstijlscript uitvoeren vanuit pad '{0}'. + InteractiveAuth = Interactieve authenticatie is ingeschakeld. Controleer de authenticatievensters om te authenticeren bij uw doelsysteem. + OutputFolder = {0} As Built Report '{1}' is opgeslagen in '{2}'. + ReportModuleInfo1 = Documentatie: https://github.com/AsBuiltReport/AsBuiltReport.{0} + ReportModuleInfo2 = Problemen of bugrapportage: https://github.com/AsBuiltReport/AsBuiltReport.{0}/issues + ReportModuleInfo3 = Vergeet niet uw rapportconfiguratiebestand bij te werken na elke nieuwe versie: https://www.asbuiltreport.com/user-guide/new-asbuiltreportconfig/ + ProjectWebsite = Raadpleeg de AsBuiltReport-projectwebsite voor meer gedetailleerde informatie: https://www.asbuiltreport.com + CommunityProject = AsBuiltReport is een door de gemeenschap onderhouden open source-project. Het heeft geen sponsoring, ondersteuning of affiliatie met technologieleveranciers, hun werknemers of gelieerde bedrijven. + ReportModuleInstalled = {0} {1} is momenteel geïnstalleerd. + ReportModuleAvailable = {0} {1} is beschikbaar. + ReportModuleUpdate = Voer 'Update-Module -Name {0} -Force' uit om de nieuwste versie te installeren. + RequiredModuleNotInstalled = {0} {1} of hoger is vereist. Voer 'Install-Module -Name {0} -RequiredVersion {1} -AllowClobber' uit om de vereiste module te installeren. + RequiredModuleTooOld = {0} {1} is momenteel geïnstalleerd. {0} {2} of hoger is vereist. Voer 'Update-Module -Name {0} -RequiredVersion {2} -Force' uit om bij te werken naar de vereiste versie. +'@ diff --git a/AsBuiltReport.Core/Language/nl-NL/New-AsBuiltReportConfig.psd1 b/AsBuiltReport.Core/Language/nl-NL/New-AsBuiltReportConfig.psd1 new file mode 100644 index 0000000..3d87576 --- /dev/null +++ b/AsBuiltReport.Core/Language/nl-NL/New-AsBuiltReportConfig.psd1 @@ -0,0 +1,11 @@ +# culture = 'nl-NL' +ConvertFrom-StringData @' + FolderNotExist = De map '{0}' bestaat niet. Maak de map aan en voer New-AsBuiltReportConfig opnieuw uit. + ProcessConfig = Verwerken van {0} rapportconfiguratiebestand van module {1}, versie {2}. + CopyConfig = Kopiëren van rapportconfiguratiebestand '{0}' naar '{1}'. + CopyModuleConfig = Kopiëren van {0} rapportconfiguratiebestand '{1}' naar '{2}'. + CreateConfig = {0} rapportconfiguratiebestand '{1}.json' aangemaakt in '{2}'. + OverWriteConfig = Kopiëren van rapportconfiguratiebestand '{0}' naar '{1}'. Bestaand bestand wordt overschreven. + ForceOverwrite = {0} rapportconfiguratiebestand '{1}.json' bestaat al in '{2}'. Gebruik '-Force' om het bestaande bestand te overschrijven. + ConfigNotFound = Rapportconfiguratiebestand niet gevonden in modulepad '{0}'. +'@ diff --git a/AsBuiltReport.Core/Language/pl-PL/AsBuiltReportCoreStyle.psd1 b/AsBuiltReport.Core/Language/pl-PL/AsBuiltReportCoreStyle.psd1 new file mode 100644 index 0000000..48ac42c --- /dev/null +++ b/AsBuiltReport.Core/Language/pl-PL/AsBuiltReportCoreStyle.psd1 @@ -0,0 +1,11 @@ +# culture = 'pl-PL' +ConvertFrom-StringData @' + Footer = Strona + Logo = Logo AsBuiltReport + CoverPageWarning = Nie można wyświetlić obrazu strony tytułowej. Ustaw 'ShowCoverPageImage' na 'false' w pliku konfiguracyjnym JSON raportu, aby uniknąć tego błędu. + CoverPage = Strona tytułowa + Author = Autor: + Date = Data: + Version = Wersja: + TOC = Spis treści +'@ diff --git a/AsBuiltReport.Core/Language/pl-PL/New-AsBuiltConfig.psd1 b/AsBuiltReport.Core/Language/pl-PL/New-AsBuiltConfig.psd1 new file mode 100644 index 0000000..77a8066 --- /dev/null +++ b/AsBuiltReport.Core/Language/pl-PL/New-AsBuiltConfig.psd1 @@ -0,0 +1,58 @@ +# culture = 'pl-PL' +@{ + +# As Built Report Information +ReportInfo = ConvertFrom-StringData @' + BannerTitle = Informacje o As Built Report + ReportAuthor = Wprowadź nazwisko autora tego raportu As Built Report [{0}] +'@ + +# Company Configuration +CompanyConfig = ConvertFrom-StringData @' + BannerTitle = Informacje o firmie + CompanyInfo = Czy chcesz wprowadzić informacje o firmie dla raportu As Built Report? (y/N) + CompanyFullName = Wprowadź pełną nazwę firmy + CompanyShortName = Wprowadź skróconą nazwę firmy + CompanyContact = Wprowadź osobę kontaktową firmy + CompanyEmail = Wprowadź adres e-mail firmy + CompanyPhone = Wprowadź numer telefonu firmy + CompanyAddress = Wprowadź adres firmy +'@ + +# Email Configuration +EmailConfig = ConvertFrom-StringData @' + BannerTitle = Konfiguracja poczty e-mail + ConfigureMailSettings = Czy chcesz wprowadzić konfigurację SMTP? (y/N) + MailServer = Wprowadź FQDN / adres IP serwera pocztowego + EmptyMailServerAddress = Adres serwera pocztowego nie może być pusty. Wprowadź prawidłowy FQDN / adres IP serwera pocztowego. + InvalidMailServer = '{0}' nie jest prawidłowym FQDN lub adresem IP. Wprowadź prawidłowy FQDN / adres IP serwera pocztowego. + MailServerPort587 = Wprowadź numer portu serwera pocztowego [587] + InvalidMailServerPort587 = Nieprawidłowy numer portu. Wprowadź liczbę z zakresu od 1 do 65535 lub naciśnij Enter, aby użyć wartości domyślnej [587]. + MailServerPort25 = Wprowadź numer portu serwera pocztowego [25] + InvalidMailServerPort25 = Nieprawidłowy numer portu. Wprowadź liczbę z zakresu od 1 do 65535 lub naciśnij Enter, aby użyć wartości domyślnej [25]. + MailServerUseSSL = Użyć SSL do połączenia z serwerem pocztowym? (y/N) + MailCredentials = Wymagane uwierzytelnianie serwera pocztowego? (y/N) + MailFrom = Wprowadź adres e-mail nadawcy + MailTo = Wprowadź adres e-mail odbiorcy + EmptyEmail = Adres e-mail nie może być pusty. Wprowadź prawidłowy adres e-mail. + InvalidEmail = '{0}' nie jest prawidłowym adresem e-mail. Wprowadź prawidłowy adres e-mail. + AnotherRecipient = Czy chcesz wprowadzić innego odbiorcę? (y/N) + MailBodyPrompt = Wprowadź treść wiadomości e-mail + MailBody = Raport As Built Report w załączniku +'@ + +# Report Configuration +ReportConfig = ConvertFrom-StringData @' + BannerTitle = Konfiguracja As Built Report + ReportConfigFolder = Wprowadź pełną ścieżkę folderu, który ma być używany do przechowywania plików konfiguracyjnych modułu raportów i niestandardowych skryptów stylu [{0}] + OverwriteReportConfig = Plik konfiguracyjny modułu raportu dla {0} już istnieje w określonym folderze. Czy chcesz go nadpisać? (y/N) + CopyFile = Kopiowanie '{0}' do '{1}'. + OverwriteFile = Kopiowanie '{0}' do '{1}'. Nadpisywanie istniejącego pliku. + SaveAsBuiltConfig = Czy chcesz zapisać plik konfiguracyjny modułu podstawowego As Built Report? (Y/n) + AsBuiltName = Wprowadź nazwę pliku konfiguracyjnego As Built Report [AsBuiltReport] + AsBuiltExportPath = Wprowadź ścieżkę do zapisania pliku konfiguracyjnego As Built Report [{0}] + ConfigFolder = Tworzenie folderu konfiguracyjnego As Built Report '{0}'. + SaveConfig = Zapisywanie pliku konfiguracyjnego As Built Report '{0}.json' w ścieżce '{1}'. + NotSaved = Plik konfiguracyjny As Built Report nie został zapisany. +'@ +} diff --git a/AsBuiltReport.Core/Language/pl-PL/New-AsBuiltReport.psd1 b/AsBuiltReport.Core/Language/pl-PL/New-AsBuiltReport.psd1 new file mode 100644 index 0000000..daa504c --- /dev/null +++ b/AsBuiltReport.Core/Language/pl-PL/New-AsBuiltReport.psd1 @@ -0,0 +1,40 @@ +# culture = 'pl-PL' +ConvertFrom-StringData @' + PwshISE = AsBuiltReport nie może być uruchomiony z Windows PowerShell ISE. Proszę użyć okna poleceń PowerShell. + Password = Hasło dla użytkownika {0} + OutputFolderPath = OutputFolderPath '{0}' nie jest prawidłową ścieżką folderu. + LoadConfig = Ładowanie konfiguracji As Built Report z {0}. + NoConfigFound = Nie można znaleźć konfiguracji As Built Report w ścieżce '{0}'. + GeneratingReport = Generowanie nowej konfiguracji As Built Report. + StyleScriptNotFound = Nie można znaleźć skryptu stylu raportu w ścieżce '{0}'. + ReportModuleNotFound = Nie można znaleźć pliku konfiguracji raportu {0} w ścieżce '{1}'. + LoadingReportConfig = Ładowanie pliku konfiguracji raportu {0} ze ścieżki '{1}'. + ReportConfigNotFound = Konfiguracja raportu nie została znaleziona w ścieżce modułu '{0}'. + SetReportFileName = Ustawianie nazwy pliku raportu na '{0}'. + EmailBannerTitle = Poświadczenia serwera e-mail + EmailCredentials = Proszę wprowadzić poświadczenia dla {0}. + InstalledModule = AsBuiltReport.Core {0} jest obecnie zainstalowany. + AvailableModule = AsBuiltReport.Core {0} jest dostępny. + UpdateModule = Uruchom 'Update-Module -Name AsBuiltReport.Core -Force', aby zainstalować najnowszą wersję. + ReportGenerating = Proszę czekać, trwa generowanie raportu {0} As Built. + ReportInitializing = > Inicjowanie struktury raportu... + DocumentStyle = > Ładowanie stylu dokumentu... + TargetSystem = > Łączenie z systemem docelowym i zbieranie danych... + ExecutionFailed = Wykonanie modułu raportu nie powiodło się: {0} + BuildingDocument = > Budowanie struktury dokumentu... + ExportingDocument = > Eksportowanie dokumentu... + Failed = [NIEPOWODZENIE] Generowanie raportu nie powiodło się + ReportStyleScript = Wykonywanie skryptu stylu raportu ze ścieżki '{0}'. + InteractiveAuth = Uwierzytelnianie interaktywne jest włączone. Sprawdź okna uwierzytelniania, aby uwierzytelnić się w systemie docelowym. + OutputFolder = {0} As Built Report '{1}' został zapisany w '{2}'. + ReportModuleInfo1 = Dokumentacja: https://github.com/AsBuiltReport/AsBuiltReport.{0} + ReportModuleInfo2 = Problemy lub zgłaszanie błędów: https://github.com/AsBuiltReport/AsBuiltReport.{0}/issues + ReportModuleInfo3 = Nie zapomnij zaktualizować pliku konfiguracji raportu po każdym nowym wydaniu: https://www.asbuiltreport.com/user-guide/new-asbuiltreportconfig/ + ProjectWebsite = Aby uzyskać bardziej szczegółowe informacje, odwiedź stronę projektu AsBuiltReport: https://www.asbuiltreport.com + CommunityProject = AsBuiltReport to projekt open source utrzymywany przez społeczność. Nie ma sponsorowania, poparcia ani powiązań z dostawcami technologii, ich pracownikami lub podmiotami stowarzyszonymi. + ReportModuleInstalled = {0} {1} jest obecnie zainstalowany. + ReportModuleAvailable = {0} {1} jest dostępny. + ReportModuleUpdate = Uruchom 'Update-Module -Name {0} -Force', aby zainstalować najnowszą wersję. + RequiredModuleNotInstalled = Wymagana jest wersja {0} {1} lub wyższa. Uruchom 'Install-Module -Name {0} -RequiredVersion {1} -AllowClobber', aby zainstalować wymagany moduł. + RequiredModuleTooOld = {0} {1} jest obecnie zainstalowany. Wymagana jest wersja {0} {2} lub wyższa. Uruchom 'Update-Module -Name {0} -RequiredVersion {2} -Force', aby zaktualizować do wymaganej wersji. +'@ diff --git a/AsBuiltReport.Core/Language/pl-PL/New-AsBuiltReportConfig.psd1 b/AsBuiltReport.Core/Language/pl-PL/New-AsBuiltReportConfig.psd1 new file mode 100644 index 0000000..8d7f26b --- /dev/null +++ b/AsBuiltReport.Core/Language/pl-PL/New-AsBuiltReportConfig.psd1 @@ -0,0 +1,11 @@ +# culture = 'pl-PL' +ConvertFrom-StringData @' + FolderNotExist = Folder '{0}' nie istnieje. Proszę utworzyć folder i uruchomić New-AsBuiltReportConfig ponownie. + ProcessConfig = Przetwarzanie pliku konfiguracyjnego raportu {0} z modułu {1}, wersja {2}. + CopyConfig = Kopiowanie pliku konfiguracyjnego raportu '{0}' do '{1}'. + CopyModuleConfig = Kopiowanie pliku konfiguracyjnego raportu {0} '{1}' do '{2}'. + CreateConfig = Plik konfiguracyjny raportu {0} '{1}.json' utworzony w '{2}'. + OverWriteConfig = Kopiowanie pliku konfiguracyjnego raportu '{0}' do '{1}'. Nadpisywanie istniejącego pliku. + ForceOverwrite = Plik konfiguracyjny raportu {0} '{1}.json' już istnieje w '{2}'. Użyj '-Force', aby nadpisać istniejący plik. + ConfigNotFound = Nie znaleziono pliku konfiguracyjnego raportu w ścieżce modułu '{0}'. +'@ diff --git a/AsBuiltReport.Core/Language/pt-PT/AsBuiltReportCoreStyle.psd1 b/AsBuiltReport.Core/Language/pt-PT/AsBuiltReportCoreStyle.psd1 new file mode 100644 index 0000000..83927b6 --- /dev/null +++ b/AsBuiltReport.Core/Language/pt-PT/AsBuiltReportCoreStyle.psd1 @@ -0,0 +1,11 @@ +# culture = 'pt-PT' +ConvertFrom-StringData @' + Footer = Página + Logo = Logótipo AsBuiltReport + CoverPageWarning = Não é possível apresentar a imagem da página de rosto. Por favor, defina 'ShowCoverPageImage' como 'false' no ficheiro de configuração JSON do relatório para evitar este erro. + CoverPage = Página de Rosto + Author = Autor: + Date = Data: + Version = Versão: + TOC = Índice +'@ diff --git a/AsBuiltReport.Core/Language/pt-PT/New-AsBuiltConfig.psd1 b/AsBuiltReport.Core/Language/pt-PT/New-AsBuiltConfig.psd1 new file mode 100644 index 0000000..9bdfe11 --- /dev/null +++ b/AsBuiltReport.Core/Language/pt-PT/New-AsBuiltConfig.psd1 @@ -0,0 +1,58 @@ +# culture = 'pt-PT' +@{ + +# As Built Report Information +ReportInfo = ConvertFrom-StringData @' + BannerTitle = Informações do As Built Report + ReportAuthor = Introduza o nome do autor para este As Built Report [{0}] +'@ + +# Company Configuration +CompanyConfig = ConvertFrom-StringData @' + BannerTitle = Informações da Empresa + CompanyInfo = Gostaria de introduzir informações da empresa para o As Built Report? (y/N) + CompanyFullName = Introduza o Nome Completo da Empresa + CompanyShortName = Introduza o Nome Abreviado da Empresa + CompanyContact = Introduza o Contacto da Empresa + CompanyEmail = Introduza o Endereço de Email da Empresa + CompanyPhone = Introduza o Número de Telefone da Empresa + CompanyAddress = Introduza o Endereço da Empresa +'@ + +# Email Configuration +EmailConfig = ConvertFrom-StringData @' + BannerTitle = Configuração de Email + ConfigureMailSettings = Gostaria de introduzir a configuração SMTP? (y/N) + MailServer = Introduza o FQDN / endereço IP do servidor de email + EmptyMailServerAddress = O endereço do servidor de email não pode estar vazio. Introduza um FQDN / endereço IP válido do servidor de email. + InvalidMailServer = '{0}' não é um FQDN ou endereço IP válido. Introduza um FQDN / endereço IP válido do servidor de email. + MailServerPort587 = Introduza o número de porta do servidor de email [587] + InvalidMailServerPort587 = Número de porta inválido. Introduza um número entre 1 e 65535, ou pressione Enter para o padrão [587]. + MailServerPort25 = Introduza o número de porta do servidor de email [25] + InvalidMailServerPort25 = Número de porta inválido. Introduza um número entre 1 e 65535, ou pressione Enter para o padrão [25]. + MailServerUseSSL = Usar SSL para a ligação ao servidor de email? (y/N) + MailCredentials = Requer autenticação no servidor de email? (y/N) + MailFrom = Introduza o endereço de email do remetente + MailTo = Introduza o endereço de email do destinatário + EmptyEmail = O endereço de email não pode estar vazio. Introduza um endereço de email válido. + InvalidEmail = '{0}' não é um endereço de email válido. Introduza um endereço de email válido. + AnotherRecipient = Deseja introduzir outro destinatário? (y/N) + MailBodyPrompt = Introduza o conteúdo do corpo da mensagem de email + MailBody = As Built Report anexado +'@ + +# Report Configuration +ReportConfig = ConvertFrom-StringData @' + BannerTitle = Configuração do As Built Report + ReportConfigFolder = Introduza o caminho completo da pasta para armazenar ficheiros de configuração do módulo de relatório e scripts de estilo personalizados [{0}] + OverwriteReportConfig = Já existe um ficheiro de configuração do módulo de relatório para {0} na pasta especificada. Gostaria de o substituir? (y/N) + CopyFile = A copiar '{0}' para '{1}'. + OverwriteFile = A copiar '{0}' para '{1}'. A substituir ficheiro existente. + SaveAsBuiltConfig = Gostaria de guardar o ficheiro de configuração do módulo core do As Built Report? (Y/n) + AsBuiltName = Introduza um nome para o ficheiro de configuração do As Built Report [AsBuiltReport] + AsBuiltExportPath = Introduza o caminho para guardar o ficheiro de configuração do As Built Report [{0}] + ConfigFolder = A criar pasta de configuração do As Built Report '{0}'. + SaveConfig = A guardar ficheiro de configuração do As Built Report '{0}.json' no caminho '{1}'. + NotSaved = Ficheiro de configuração do As Built Report não guardado. +'@ +} diff --git a/AsBuiltReport.Core/Language/pt-PT/New-AsBuiltReport.psd1 b/AsBuiltReport.Core/Language/pt-PT/New-AsBuiltReport.psd1 new file mode 100644 index 0000000..0bbe9da --- /dev/null +++ b/AsBuiltReport.Core/Language/pt-PT/New-AsBuiltReport.psd1 @@ -0,0 +1,40 @@ +# culture = 'pt-PT' +ConvertFrom-StringData @' + PwshISE = AsBuiltReport não pode ser executado no Windows PowerShell ISE. Por favor, use uma janela de comando do PowerShell. + Password = Senha para o usuário {0} + OutputFolderPath = OutputFolderPath '{0}' não é um caminho de pasta válido. + LoadConfig = Carregando configuração do As Built Report de {0}. + NoConfigFound = Não foi possível encontrar a configuração do As Built Report no caminho '{0}'. + GeneratingReport = Gerando nova configuração do As Built Report. + StyleScriptNotFound = Não foi possível encontrar o script de estilo do relatório no caminho '{0}'. + ReportModuleNotFound = Não foi possível encontrar o arquivo de configuração do relatório {0} no caminho '{1}'. + LoadingReportConfig = Carregando arquivo de configuração do relatório {0} do caminho '{1}'. + ReportConfigNotFound = Configuração do relatório não encontrada no caminho do módulo '{0}'. + SetReportFileName = Definindo o nome do arquivo do relatório como '{0}'. + EmailBannerTitle = Credenciais do Servidor de Email + EmailCredentials = Por favor, insira as credenciais para {0}. + InstalledModule = AsBuiltReport.Core {0} está atualmente instalado. + AvailableModule = AsBuiltReport.Core {0} está disponível. + UpdateModule = Execute 'Update-Module -Name AsBuiltReport.Core -Force' para instalar a versão mais recente. + ReportGenerating = Por favor, aguarde enquanto o relatório {0} As Built está sendo gerado. + ReportInitializing = > Inicializando estrutura do relatório... + DocumentStyle = > Carregando estilo do documento... + TargetSystem = > Conectando ao sistema de destino e coletando dados... + ExecutionFailed = Execução do módulo de relatório falhou: {0} + BuildingDocument = > Construindo estrutura do documento... + ExportingDocument = > Exportando documento... + Failed = [FALHOU] Geração do relatório falhou + ReportStyleScript = Executando script de estilo do relatório do caminho '{0}'. + InteractiveAuth = A autenticação interativa está habilitada. Por favor, verifique as janelas de autenticação para se autenticar no seu sistema de destino. + OutputFolder = {0} As Built Report '{1}' foi salvo em '{2}'. + ReportModuleInfo1 = Documentação: https://github.com/AsBuiltReport/AsBuiltReport.{0} + ReportModuleInfo2 = Problemas ou relatório de bugs: https://github.com/AsBuiltReport/AsBuiltReport.{0}/issues + ReportModuleInfo3 = Não se esqueça de atualizar o arquivo de configuração do relatório após cada nova versão: https://www.asbuiltreport.com/user-guide/new-asbuiltreportconfig/ + ProjectWebsite = Consulte o site do projeto AsBuiltReport para obter informações mais detalhadas: https://www.asbuiltreport.com + CommunityProject = AsBuiltReport é um projeto de código aberto mantido pela comunidade. Não tem patrocínio, endosso ou afiliação com fornecedores de tecnologia, seus funcionários ou afiliados. + ReportModuleInstalled = {0} {1} está atualmente instalado. + ReportModuleAvailable = {0} {1} está disponível. + ReportModuleUpdate = Execute 'Update-Module -Name {0} -Force' para instalar a versão mais recente. + RequiredModuleNotInstalled = {0} {1} ou superior é necessário. Execute 'Install-Module -Name {0} -RequiredVersion {1} -AllowClobber' para instalar o módulo necessário. + RequiredModuleTooOld = {0} {1} está atualmente instalado. {0} {2} ou superior é necessário. Execute 'Update-Module -Name {0} -RequiredVersion {2} -Force' para atualizar para a versão necessária. +'@ diff --git a/AsBuiltReport.Core/Language/pt-PT/New-AsBuiltReportConfig.psd1 b/AsBuiltReport.Core/Language/pt-PT/New-AsBuiltReportConfig.psd1 new file mode 100644 index 0000000..8430c93 --- /dev/null +++ b/AsBuiltReport.Core/Language/pt-PT/New-AsBuiltReportConfig.psd1 @@ -0,0 +1,11 @@ +# culture = 'pt-PT' +ConvertFrom-StringData @' + FolderNotExist = A pasta '{0}' não existe. Crie a pasta e execute New-AsBuiltReportConfig novamente. + ProcessConfig = A processar o ficheiro de configuração do relatório {0} do módulo {1}, versão {2}. + CopyConfig = A copiar o ficheiro de configuração do relatório '{0}' para '{1}'. + CopyModuleConfig = A copiar o ficheiro de configuração do relatório {0} '{1}' para '{2}'. + CreateConfig = Ficheiro de configuração do relatório {0} '{1}.json' criado em '{2}'. + OverWriteConfig = A copiar o ficheiro de configuração do relatório '{0}' para '{1}'. A substituir ficheiro existente. + ForceOverwrite = O ficheiro de configuração do relatório {0} '{1}.json' já existe em '{2}'. Use '-Force' para substituir o ficheiro existente. + ConfigNotFound = Ficheiro de configuração do relatório não encontrado no caminho do módulo '{0}'. +'@ diff --git a/AsBuiltReport.Core/Language/ru-RU/AsBuiltReportCoreStyle.psd1 b/AsBuiltReport.Core/Language/ru-RU/AsBuiltReportCoreStyle.psd1 new file mode 100644 index 0000000..d8ae2c1 --- /dev/null +++ b/AsBuiltReport.Core/Language/ru-RU/AsBuiltReportCoreStyle.psd1 @@ -0,0 +1,11 @@ +# culture = 'ru-RU' +ConvertFrom-StringData @' + Footer = Страница + Logo = Логотип AsBuiltReport + CoverPageWarning = Невозможно отобразить изображение титульной страницы. Пожалуйста, установите 'ShowCoverPageImage' в 'false' в файле конфигурации JSON отчета, чтобы избежать этой ошибки. + CoverPage = Титульная страница + Author = Автор: + Date = Дата: + Version = Версия: + TOC = Оглавление +'@ diff --git a/AsBuiltReport.Core/Language/ru-RU/New-AsBuiltConfig.psd1 b/AsBuiltReport.Core/Language/ru-RU/New-AsBuiltConfig.psd1 new file mode 100644 index 0000000..9cb91b5 --- /dev/null +++ b/AsBuiltReport.Core/Language/ru-RU/New-AsBuiltConfig.psd1 @@ -0,0 +1,58 @@ +# culture = 'ru-RU' +@{ + +# As Built Report Information +ReportInfo = ConvertFrom-StringData @' + BannerTitle = Информация об As Built Report + ReportAuthor = Введите имя автора этого As Built Report [{0}] +'@ + +# Company Configuration +CompanyConfig = ConvertFrom-StringData @' + BannerTitle = Информация о компании + CompanyInfo = Хотите ввести информацию о компании для As Built Report? (y/N) + CompanyFullName = Введите полное название компании + CompanyShortName = Введите краткое название компании + CompanyContact = Введите контактное лицо компании + CompanyEmail = Введите адрес электронной почты компании + CompanyPhone = Введите номер телефона компании + CompanyAddress = Введите адрес компании +'@ + +# Email Configuration +EmailConfig = ConvertFrom-StringData @' + BannerTitle = Настройка электронной почты + ConfigureMailSettings = Хотите ввести конфигурацию SMTP? (y/N) + MailServer = Введите FQDN / IP-адрес почтового сервера + EmptyMailServerAddress = Адрес почтового сервера не может быть пустым. Введите действительный FQDN / IP-адрес почтового сервера. + InvalidMailServer = '{0}' не является действительным FQDN или IP-адресом. Введите действительный FQDN / IP-адрес почтового сервера. + MailServerPort587 = Введите номер порта почтового сервера [587] + InvalidMailServerPort587 = Неверный номер порта. Введите число от 1 до 65535 или нажмите Enter для значения по умолчанию [587]. + MailServerPort25 = Введите номер порта почтового сервера [25] + InvalidMailServerPort25 = Неверный номер порта. Введите число от 1 до 65535 или нажмите Enter для значения по умолчанию [25]. + MailServerUseSSL = Использовать SSL для подключения к почтовому серверу? (y/N) + MailCredentials = Требуется аутентификация на почтовом сервере? (y/N) + MailFrom = Введите адрес электронной почты отправителя + MailTo = Введите адрес электронной почты получателя + EmptyEmail = Адрес электронной почты не может быть пустым. Введите действительный адрес электронной почты. + InvalidEmail = '{0}' не является действительным адресом электронной почты. Введите действительный адрес электронной почты. + AnotherRecipient = Хотите ввести другого получателя? (y/N) + MailBodyPrompt = Введите содержимое тела электронного письма + MailBody = As Built Report прикреплен +'@ + +# Report Configuration +ReportConfig = ConvertFrom-StringData @' + BannerTitle = Конфигурация As Built Report + ReportConfigFolder = Введите полный путь к папке для хранения файлов конфигурации модуля отчетов и пользовательских скриптов стилей [{0}] + OverwriteReportConfig = Файл конфигурации модуля отчета для {0} уже существует в указанной папке. Хотите перезаписать его? (y/N) + CopyFile = Копирование '{0}' в '{1}'. + OverwriteFile = Копирование '{0}' в '{1}'. Перезапись существующего файла. + SaveAsBuiltConfig = Хотите сохранить файл конфигурации основного модуля As Built Report? (Y/n) + AsBuiltName = Введите имя для файла конфигурации As Built Report [AsBuiltReport] + AsBuiltExportPath = Введите путь для сохранения файла конфигурации As Built Report [{0}] + ConfigFolder = Создание папки конфигурации As Built Report '{0}'. + SaveConfig = Сохранение файла конфигурации As Built Report '{0}.json' по пути '{1}'. + NotSaved = Файл конфигурации As Built Report не сохранен. +'@ +} diff --git a/AsBuiltReport.Core/Language/ru-RU/New-AsBuiltReport.psd1 b/AsBuiltReport.Core/Language/ru-RU/New-AsBuiltReport.psd1 new file mode 100644 index 0000000..9091c3f --- /dev/null +++ b/AsBuiltReport.Core/Language/ru-RU/New-AsBuiltReport.psd1 @@ -0,0 +1,40 @@ +# culture = 'ru-RU' +ConvertFrom-StringData @' + PwshISE = AsBuiltReport не может быть запущен из Windows PowerShell ISE. Пожалуйста, используйте командное окно PowerShell. + Password = Пароль для пользователя {0} + OutputFolderPath = OutputFolderPath '{0}' не является допустимым путем к папке. + LoadConfig = Загрузка конфигурации As Built Report из {0}. + NoConfigFound = Не удалось найти конфигурацию As Built Report по пути '{0}'. + GeneratingReport = Создание новой конфигурации As Built Report. + StyleScriptNotFound = Не удалось найти скрипт стиля отчета по пути '{0}'. + ReportModuleNotFound = Не удалось найти файл конфигурации отчета {0} по пути '{1}'. + LoadingReportConfig = Загрузка файла конфигурации отчета {0} из пути '{1}'. + ReportConfigNotFound = Конфигурация отчета не найдена по пути модуля '{0}'. + SetReportFileName = Установка имени файла отчета на '{0}'. + EmailBannerTitle = Учетные данные почтового сервера + EmailCredentials = Пожалуйста, введите учетные данные для {0}. + InstalledModule = AsBuiltReport.Core {0} в настоящее время установлен. + AvailableModule = AsBuiltReport.Core {0} доступен. + UpdateModule = Запустите 'Update-Module -Name AsBuiltReport.Core -Force' для установки последней версии. + ReportGenerating = Пожалуйста, подождите, пока создается отчет {0} As Built. + ReportInitializing = > Инициализация фреймворка отчета... + DocumentStyle = > Загрузка стиля документа... + TargetSystem = > Подключение к целевой системе и сбор данных... + ExecutionFailed = Ошибка выполнения модуля отчета: {0} + BuildingDocument = > Построение структуры документа... + ExportingDocument = > Экспорт документа... + Failed = [ОШИБКА] Создание отчета не удалось + ReportStyleScript = Выполнение скрипта стиля отчета из пути '{0}'. + InteractiveAuth = Интерактивная аутентификация включена. Пожалуйста, проверьте окна аутентификации для прохождения аутентификации в целевой системе. + OutputFolder = {0} As Built Report '{1}' сохранен в '{2}'. + ReportModuleInfo1 = Документация: https://github.com/AsBuiltReport/AsBuiltReport.{0} + ReportModuleInfo2 = Проблемы или сообщения об ошибках: https://github.com/AsBuiltReport/AsBuiltReport.{0}/issues + ReportModuleInfo3 = Не забудьте обновить файл конфигурации отчета после каждого нового выпуска версии: https://www.asbuiltreport.com/user-guide/new-asbuiltreportconfig/ + ProjectWebsite = Пожалуйста, обратитесь к веб-сайту проекта AsBuiltReport для получения более подробной информации: https://www.asbuiltreport.com + CommunityProject = AsBuiltReport - это проект с открытым исходным кодом, поддерживаемый сообществом. Он не имеет спонсорства, одобрения или связи с какими-либо поставщиками технологий, их сотрудниками или аффилированными лицами. + ReportModuleInstalled = {0} {1} в настоящее время установлен. + ReportModuleAvailable = {0} {1} доступен. + ReportModuleUpdate = Запустите 'Update-Module -Name {0} -Force' для установки последней версии. + RequiredModuleNotInstalled = Требуется {0} {1} или выше. Запустите 'Install-Module -Name {0} -RequiredVersion {1} -AllowClobber' для установки необходимого модуля. + RequiredModuleTooOld = {0} {1} в настоящее время установлен. Требуется {0} {2} или выше. Запустите 'Update-Module -Name {0} -RequiredVersion {2} -Force' для обновления до требуемой версии. +'@ diff --git a/AsBuiltReport.Core/Language/ru-RU/New-AsBuiltReportConfig.psd1 b/AsBuiltReport.Core/Language/ru-RU/New-AsBuiltReportConfig.psd1 new file mode 100644 index 0000000..1b2bb08 --- /dev/null +++ b/AsBuiltReport.Core/Language/ru-RU/New-AsBuiltReportConfig.psd1 @@ -0,0 +1,11 @@ +# culture = 'ru-RU' +ConvertFrom-StringData @' + FolderNotExist = Папка '{0}' не существует. Создайте папку и запустите New-AsBuiltReportConfig снова. + ProcessConfig = Обработка файла конфигурации отчета {0} из модуля {1}, версия {2}. + CopyConfig = Копирование файла конфигурации отчета '{0}' в '{1}'. + CopyModuleConfig = Копирование файла конфигурации отчета {0} '{1}' в '{2}'. + CreateConfig = Файл конфигурации отчета {0} '{1}.json' создан в '{2}'. + OverWriteConfig = Копирование файла конфигурации отчета '{0}' в '{1}'. Перезапись существующего файла. + ForceOverwrite = Файл конфигурации отчета {0} '{1}.json' уже существует в '{2}'. Используйте '-Force' для перезаписи существующего файла. + ConfigNotFound = Файл конфигурации отчета не найден в пути модуля '{0}'. +'@ diff --git a/AsBuiltReport.Core/Language/sv-SE/AsBuiltReportCoreStyle.psd1 b/AsBuiltReport.Core/Language/sv-SE/AsBuiltReportCoreStyle.psd1 new file mode 100644 index 0000000..e121bc8 --- /dev/null +++ b/AsBuiltReport.Core/Language/sv-SE/AsBuiltReportCoreStyle.psd1 @@ -0,0 +1,11 @@ +# culture = 'sv-SE' +ConvertFrom-StringData @' + Footer = Sida + Logo = AsBuiltReport Logotyp + CoverPageWarning = Kan inte visa omslagsbild. Vänligen ställ in 'ShowCoverPageImage' till 'false' i rapportens JSON-konfigurationsfil för att undvika detta fel. + CoverPage = Omslagssida + Author = Författare: + Date = Datum: + Version = Version: + TOC = Innehållsförteckning +'@ diff --git a/AsBuiltReport.Core/Language/sv-SE/New-AsBuiltConfig.psd1 b/AsBuiltReport.Core/Language/sv-SE/New-AsBuiltConfig.psd1 new file mode 100644 index 0000000..9721097 --- /dev/null +++ b/AsBuiltReport.Core/Language/sv-SE/New-AsBuiltConfig.psd1 @@ -0,0 +1,58 @@ +# culture = 'sv-SE' +@{ + +# As Built Report Information +ReportInfo = ConvertFrom-StringData @' + BannerTitle = As Built Report Information + ReportAuthor = Ange namnet på författaren för denna As Built Report [{0}] +'@ + +# Company Configuration +CompanyConfig = ConvertFrom-StringData @' + BannerTitle = Företagsinformation + CompanyInfo = Vill du ange företagsinformation för As Built Report? (y/N) + CompanyFullName = Ange företagets fullständiga namn + CompanyShortName = Ange företagets kortnamn + CompanyContact = Ange företagskontakt + CompanyEmail = Ange företagets e-postadress + CompanyPhone = Ange företagets telefonnummer + CompanyAddress = Ange företagsadress +'@ + +# Email Configuration +EmailConfig = ConvertFrom-StringData @' + BannerTitle = E-postkonfiguration + ConfigureMailSettings = Vill du ange SMTP-konfiguration? (y/N) + MailServer = Ange e-postserverns FQDN / IP-adress + EmptyMailServerAddress = E-postserverns adress får inte vara tom. Ange ett giltigt FQDN / IP-adress för e-postservern. + InvalidMailServer = '{0}' är inte ett giltigt FQDN eller IP-adress. Ange ett giltigt FQDN / IP-adress för e-postservern. + MailServerPort587 = Ange e-postserverns portnummer [587] + InvalidMailServerPort587 = Ogiltigt portnummer. Ange ett nummer mellan 1 och 65535, eller tryck på Enter för standardvärdet [587]. + MailServerPort25 = Ange e-postserverns portnummer [25] + InvalidMailServerPort25 = Ogiltigt portnummer. Ange ett nummer mellan 1 och 65535, eller tryck på Enter för standardvärdet [25]. + MailServerUseSSL = Använd SSL för e-postserveranslutning? (y/N) + MailCredentials = Kräver e-postservern autentisering? (y/N) + MailFrom = Ange avsändarens e-postadress + MailTo = Ange mottagarens e-postadress + EmptyEmail = E-postadress får inte vara tom. Ange en giltig e-postadress. + InvalidEmail = '{0}' är inte en giltig e-postadress. Ange en giltig e-postadress. + AnotherRecipient = Vill du ange en annan mottagare? (y/N) + MailBodyPrompt = Ange innehållet i e-postmeddelandets brödtext + MailBody = As Built Report bifogad +'@ + +# Report Configuration +ReportConfig = ConvertFrom-StringData @' + BannerTitle = As Built Report Konfiguration + ReportConfigFolder = Ange den fullständiga sökvägen till mappen som ska användas för att lagra rapportmodulens konfigurationsfiler och anpassade formatskript [{0}] + OverwriteReportConfig = En konfigurationsfil för rapportmodulen för {0} finns redan i den angivna mappen. Vill du skriva över den? (y/N) + CopyFile = Kopierar '{0}' till '{1}'. + OverwriteFile = Kopierar '{0}' till '{1}'. Skriver över befintlig fil. + SaveAsBuiltConfig = Vill du spara konfigurationsfilen för As Built Report kärnmodul? (Y/n) + AsBuiltName = Ange ett namn för As Built Report-konfigurationsfilen [AsBuiltReport] + AsBuiltExportPath = Ange sökvägen för att spara As Built Report-konfigurationsfilen [{0}] + ConfigFolder = Skapar As Built Report-konfigurationsmapp '{0}'. + SaveConfig = Sparar As Built Report-konfigurationsfil '{0}.json' till sökväg '{1}'. + NotSaved = As Built Report-konfigurationsfilen sparades inte. +'@ +} diff --git a/AsBuiltReport.Core/Language/sv-SE/New-AsBuiltReport.psd1 b/AsBuiltReport.Core/Language/sv-SE/New-AsBuiltReport.psd1 new file mode 100644 index 0000000..88051f7 --- /dev/null +++ b/AsBuiltReport.Core/Language/sv-SE/New-AsBuiltReport.psd1 @@ -0,0 +1,40 @@ +# culture = 'sv-SE' +ConvertFrom-StringData @' + PwshISE = AsBuiltReport kan inte köras från Windows PowerShell ISE. Använd ett PowerShell-kommandofönster istället. + Password = Lösenord för användare {0} + OutputFolderPath = OutputFolderPath '{0}' är inte en giltig mappsökväg. + LoadConfig = Laddar As Built Report-konfiguration från {0}. + NoConfigFound = Kunde inte hitta As Built Report-konfiguration i sökvägen '{0}'. + GeneratingReport = Genererar ny As Built Report-konfiguration. + StyleScriptNotFound = Kunde inte hitta rapportstilskript i sökvägen '{0}'. + ReportModuleNotFound = Kunde inte hitta {0} rapportkonfigurationsfil i sökvägen '{1}'. + LoadingReportConfig = Laddar {0} rapportkonfigurationsfil från sökvägen '{1}'. + ReportConfigNotFound = Rapportkonfiguration hittades inte i modulsökvägen '{0}'. + SetReportFileName = Ställer in rapportfilnamn till '{0}'. + EmailBannerTitle = E-postserverreferenser + EmailCredentials = Ange autentiseringsuppgifter för {0}. + InstalledModule = AsBuiltReport.Core {0} är för närvarande installerat. + AvailableModule = AsBuiltReport.Core {0} är tillgängligt. + UpdateModule = Kör 'Update-Module -Name AsBuiltReport.Core -Force' för att installera den senaste versionen. + ReportGenerating = Vänta medan {0} As Built Report genereras. + ReportInitializing = > Initierar rapportramverk... + DocumentStyle = > Laddar dokumentstil... + TargetSystem = > Ansluter till målsystem och samlar in data... + ExecutionFailed = Körning av rapportmodul misslyckades: {0} + BuildingDocument = > Bygger dokumentstruktur... + ExportingDocument = > Exporterar dokument... + Failed = [MISSLYCKADES] Rapportgenerering misslyckades + ReportStyleScript = Kör rapportstilskript från sökvägen '{0}'. + InteractiveAuth = Interaktiv autentisering är aktiverad. Kontrollera autentiseringsfönster för att autentisera till ditt målsystem. + OutputFolder = {0} As Built Report '{1}' har sparats till '{2}'. + ReportModuleInfo1 = Dokumentation: https://github.com/AsBuiltReport/AsBuiltReport.{0} + ReportModuleInfo2 = Problem eller felrapportering: https://github.com/AsBuiltReport/AsBuiltReport.{0}/issues + ReportModuleInfo3 = Glöm inte att uppdatera din rapportkonfigurationsfil efter varje ny versionsutgåva: https://www.asbuiltreport.com/user-guide/new-asbuiltreportconfig/ + ProjectWebsite = Se AsBuiltReport-projektets webbplats för mer detaljerad information: https://www.asbuiltreport.com + CommunityProject = AsBuiltReport är ett community-underhållet öppen källkod-projekt. Det har inget sponsorskap, godkännande eller koppling till några teknikleverantörer, deras anställda eller närstående företag. + ReportModuleInstalled = {0} {1} är för närvarande installerat. + ReportModuleAvailable = {0} {1} är tillgängligt. + ReportModuleUpdate = Kör 'Update-Module -Name {0} -Force' för att installera den senaste versionen. + RequiredModuleNotInstalled = {0} {1} eller högre krävs. Kör 'Install-Module -Name {0} -RequiredVersion {1} -AllowClobber' för att installera den nödvändiga modulen. + RequiredModuleTooOld = {0} {1} är för närvarande installerat. {0} {2} eller högre krävs. Kör 'Update-Module -Name {0} -RequiredVersion {2} -Force' för att uppdatera till den nödvändiga versionen. +'@ diff --git a/AsBuiltReport.Core/Language/sv-SE/New-AsBuiltReportConfig.psd1 b/AsBuiltReport.Core/Language/sv-SE/New-AsBuiltReportConfig.psd1 new file mode 100644 index 0000000..5118f6b --- /dev/null +++ b/AsBuiltReport.Core/Language/sv-SE/New-AsBuiltReportConfig.psd1 @@ -0,0 +1,11 @@ +# culture = 'sv-SE' +ConvertFrom-StringData @' + FolderNotExist = Mappen '{0}' finns inte. Skapa mappen och kör New-AsBuiltReportConfig igen. + ProcessConfig = Bearbetar {0} rapportkonfigurationsfil från modul {1}, version {2}. + CopyConfig = Kopierar rapportkonfigurationsfil '{0}' till '{1}'. + CopyModuleConfig = Kopierar {0} rapportkonfigurationsfil '{1}' till '{2}'. + CreateConfig = {0} rapportkonfigurationsfil '{1}.json' skapad i '{2}'. + OverWriteConfig = Kopierar rapportkonfigurationsfil '{0}' till '{1}'. Skriver över befintlig fil. + ForceOverwrite = {0} rapportkonfigurationsfil '{1}.json' finns redan i '{2}'. Använd '-Force' för att skriva över befintlig fil. + ConfigNotFound = Rapportkonfigurationsfil hittades inte i modulsökväg '{0}'. +'@ diff --git a/AsBuiltReport.Core/Language/th-TH/AsBuiltReportCoreStyle.psd1 b/AsBuiltReport.Core/Language/th-TH/AsBuiltReportCoreStyle.psd1 new file mode 100644 index 0000000..b15044b --- /dev/null +++ b/AsBuiltReport.Core/Language/th-TH/AsBuiltReportCoreStyle.psd1 @@ -0,0 +1,11 @@ +# culture = 'th-TH' +ConvertFrom-StringData @' + Footer = หน้า + Logo = โลโก้ AsBuiltReport + CoverPageWarning = ไม่สามารถแสดงภาพหน้าปก โปรดตั้งค่า 'ShowCoverPageImage' เป็น 'false' ในไฟล์กำหนดค่า JSON ของรายงานเพื่อหลีกเลี่ยงข้อผิดพลาดนี้ + CoverPage = หน้าปก + Author = ผู้เขียน: + Date = วันที่: + Version = เวอร์ชัน: + TOC = สารบัญ +'@ diff --git a/AsBuiltReport.Core/Language/th-TH/New-AsBuiltConfig.psd1 b/AsBuiltReport.Core/Language/th-TH/New-AsBuiltConfig.psd1 new file mode 100644 index 0000000..2c749f3 --- /dev/null +++ b/AsBuiltReport.Core/Language/th-TH/New-AsBuiltConfig.psd1 @@ -0,0 +1,58 @@ +# culture = 'th-TH' +@{ + +# As Built Report Information +ReportInfo = ConvertFrom-StringData @' + BannerTitle = ข้อมูล As Built Report + ReportAuthor = ป้อนชื่อผู้เขียนสำหรับ As Built Report นี้ [{0}] +'@ + +# Company Configuration +CompanyConfig = ConvertFrom-StringData @' + BannerTitle = ข้อมูลบริษัท + CompanyInfo = คุณต้องการป้อนข้อมูลบริษัทสำหรับ As Built Report หรือไม่? (y/N) + CompanyFullName = ป้อนชื่อบริษัทแบบเต็ม + CompanyShortName = ป้อนชื่อบริษัทแบบย่อ + CompanyContact = ป้อนผู้ติดต่อบริษัท + CompanyEmail = ป้อนที่อยู่อีเมลของบริษัท + CompanyPhone = ป้อนหมายเลขโทรศัพท์ของบริษัท + CompanyAddress = ป้อนที่อยู่ของบริษัท +'@ + +# Email Configuration +EmailConfig = ConvertFrom-StringData @' + BannerTitle = การกำหนดค่าอีเมล + ConfigureMailSettings = คุณต้องการป้อนการกำหนดค่า SMTP หรือไม่? (y/N) + MailServer = ป้อน FQDN / ที่อยู่ IP ของเซิร์ฟเวอร์เมล + EmptyMailServerAddress = ที่อยู่เซิร์ฟเวอร์เมลต้องไม่ว่างเปล่า โปรดป้อน FQDN / ที่อยู่ IP ที่ถูกต้องของเซิร์ฟเวอร์เมล + InvalidMailServer = '{0}' ไม่ใช่ FQDN หรือที่อยู่ IP ที่ถูกต้อง โปรดป้อน FQDN / ที่อยู่ IP ที่ถูกต้องของเซิร์ฟเวอร์เมล + MailServerPort587 = ป้อนหมายเลขพอร์ตของเซิร์ฟเวอร์เมล [587] + InvalidMailServerPort587 = หมายเลขพอร์ตไม่ถูกต้อง โปรดป้อนตัวเลขระหว่าง 1 ถึง 65535 หรือกด Enter สำหรับค่าเริ่มต้น [587] + MailServerPort25 = ป้อนหมายเลขพอร์ตของเซิร์ฟเวอร์เมล [25] + InvalidMailServerPort25 = หมายเลขพอร์ตไม่ถูกต้อง โปรดป้อนตัวเลขระหว่าง 1 ถึง 65535 หรือกด Enter สำหรับค่าเริ่มต้น [25] + MailServerUseSSL = ใช้ SSL สำหรับการเชื่อมต่อเซิร์ฟเวอร์เมลหรือไม่? (y/N) + MailCredentials = ต้องการการตรวจสอบสิทธิ์เซิร์ฟเวอร์เมลหรือไม่? (y/N) + MailFrom = ป้อนที่อยู่อีเมลของผู้ส่ง + MailTo = ป้อนที่อยู่อีเมลของผู้รับ + EmptyEmail = ที่อยู่อีเมลต้องไม่ว่างเปล่า โปรดป้อนที่อยู่อีเมลที่ถูกต้อง + InvalidEmail = '{0}' ไม่ใช่ที่อยู่อีเมลที่ถูกต้อง โปรดป้อนที่อยู่อีเมลที่ถูกต้อง + AnotherRecipient = คุณต้องการป้อนผู้รับรายอื่นหรือไม่? (y/N) + MailBodyPrompt = ป้อนเนื้อหาข้อความอีเมล + MailBody = แนบ As Built Report +'@ + +# Report Configuration +ReportConfig = ConvertFrom-StringData @' + BannerTitle = การกำหนดค่า As Built Report + ReportConfigFolder = ป้อนเส้นทางเต็มของโฟลเดอร์ที่จะใช้สำหรับจัดเก็บไฟล์การกำหนดค่าโมดูลรายงานและสคริปต์สไตล์แบบกำหนดเอง [{0}] + OverwriteReportConfig = ไฟล์การกำหนดค่าโมดูลรายงานสำหรับ {0} มีอยู่แล้วในโฟลเดอร์ที่ระบุ คุณต้องการเขียนทับหรือไม่? (y/N) + CopyFile = กำลังคัดลอก '{0}' ไปยัง '{1}' + OverwriteFile = กำลังคัดลอก '{0}' ไปยัง '{1}' กำลังเขียนทับไฟล์ที่มีอยู่ + SaveAsBuiltConfig = คุณต้องการบันทึกไฟล์การกำหนดค่าโมดูลหลักของ As Built Report หรือไม่? (Y/n) + AsBuiltName = ป้อนชื่อสำหรับไฟล์การกำหนดค่า As Built Report [AsBuiltReport] + AsBuiltExportPath = ป้อนเส้นทางเพื่อบันทึกไฟล์การกำหนดค่า As Built Report [{0}] + ConfigFolder = กำลังสร้างโฟลเดอร์การกำหนดค่า As Built Report '{0}' + SaveConfig = กำลังบันทึกไฟล์การกำหนดค่า As Built Report '{0}.json' ไปยังเส้นทาง '{1}' + NotSaved = ไม่ได้บันทึกไฟล์การกำหนดค่า As Built Report +'@ +} diff --git a/AsBuiltReport.Core/Language/th-TH/New-AsBuiltReport.psd1 b/AsBuiltReport.Core/Language/th-TH/New-AsBuiltReport.psd1 new file mode 100644 index 0000000..ea677aa --- /dev/null +++ b/AsBuiltReport.Core/Language/th-TH/New-AsBuiltReport.psd1 @@ -0,0 +1,40 @@ +# culture = 'th-TH' +ConvertFrom-StringData @' + PwshISE = ไม่สามารถเรียกใช้ AsBuiltReport จาก Windows PowerShell ISE กรุณาใช้หน้าต่างคำสั่ง PowerShell แทน + Password = รหัสผ่านสำหรับผู้ใช้ {0} + OutputFolderPath = OutputFolderPath '{0}' ไม่ใช่เส้นทางโฟลเดอร์ที่ถูกต้อง + LoadConfig = กำลังโหลดการกำหนดค่า As Built Report จาก {0} + NoConfigFound = ไม่พบการกำหนดค่า As Built Report ในเส้นทาง '{0}' + GeneratingReport = กำลังสร้างการกำหนดค่า As Built Report ใหม่ + StyleScriptNotFound = ไม่พบสคริปต์สไตล์รายงานในเส้นทาง '{0}' + ReportModuleNotFound = ไม่พบไฟล์การกำหนดค่ารายงาน {0} ในเส้นทาง '{1}' + LoadingReportConfig = กำลังโหลดไฟล์การกำหนดค่ารายงาน {0} จากเส้นทาง '{1}' + ReportConfigNotFound = ไม่พบการกำหนดค่ารายงานในเส้นทางโมดูล '{0}' + SetReportFileName = กำลังตั้งชื่อไฟล์รายงานเป็น '{0}' + EmailBannerTitle = ข้อมูลรับรองเซิร์ฟเวอร์อีเมล + EmailCredentials = กรุณากรอกข้อมูลรับรองสำหรับ {0} + InstalledModule = AsBuiltReport.Core {0} ติดตั้งอยู่ในปัจจุบัน + AvailableModule = AsBuiltReport.Core {0} พร้อมใช้งาน + UpdateModule = เรียกใช้ 'Update-Module -Name AsBuiltReport.Core -Force' เพื่อติดตั้งเวอร์ชันล่าสุด + ReportGenerating = กรุณารอสักครู่ในขณะที่รายงาน {0} As Built กำลังถูกสร้าง + ReportInitializing = > กำลังเริ่มต้นเฟรมเวิร์กรายงาน... + DocumentStyle = > กำลังโหลดสไตล์เอกสาร... + TargetSystem = > กำลังเชื่อมต่อกับระบบเป้าหมายและรวบรวมข้อมูล... + ExecutionFailed = การดำเนินการโมดูลรายงานล้มเหลว: {0} + BuildingDocument = > กำลังสร้างโครงสร้างเอกสาร... + ExportingDocument = > กำลังส่งออกเอกสาร... + Failed = [ล้มเหลว] การสร้างรายงานล้มเหลว + ReportStyleScript = กำลังดำเนินการสคริปต์สไตล์รายงานจากเส้นทาง '{0}' + InteractiveAuth = เปิดใช้งานการยืนยันตัวตนแบบโต้ตอบแล้ว กรุณาตรวจสอบหน้าต่างการยืนยันตัวตนเพื่อยืนยันตัวตนกับระบบเป้าหมายของคุณ + OutputFolder = {0} As Built Report '{1}' ได้รับการบันทึกไปยัง '{2}' แล้ว + ReportModuleInfo1 = เอกสาร: https://github.com/AsBuiltReport/AsBuiltReport.{0} + ReportModuleInfo2 = ปัญหาหรือการรายงานข้อบกพร่อง: https://github.com/AsBuiltReport/AsBuiltReport.{0}/issues + ReportModuleInfo3 = อย่าลืมอัปเดตไฟล์การกำหนดค่ารายงานของคุณหลังจากการออกเวอร์ชันใหม่แต่ละครั้ง: https://www.asbuiltreport.com/user-guide/new-asbuiltreportconfig/ + ProjectWebsite = โปรดดูเว็บไซต์โครงการ AsBuiltReport สำหรับข้อมูลโดยละเอียดเพิ่มเติม: https://www.asbuiltreport.com + CommunityProject = AsBuiltReport เป็นโครงการโอเพนซอร์สที่ดูแลโดยชุมชน ไม่มีการสนับสนุน การรับรอง หรือความเกี่ยวข้องกับผู้จัดจำหน่ายเทคโนโลยีใดๆ พนักงาน หรือบริษัทในเครือ + ReportModuleInstalled = {0} {1} ติดตั้งอยู่ในปัจจุบัน + ReportModuleAvailable = {0} {1} พร้อมใช้งาน + ReportModuleUpdate = เรียกใช้ 'Update-Module -Name {0} -Force' เพื่อติดตั้งเวอร์ชันล่าสุด + RequiredModuleNotInstalled = ต้องการ {0} {1} หรือสูงกว่า เรียกใช้ 'Install-Module -Name {0} -RequiredVersion {1} -AllowClobber' เพื่อติดตั้งโมดูลที่ต้องการ + RequiredModuleTooOld = {0} {1} ติดตั้งอยู่ในปัจจุบัน ต้องการ {0} {2} หรือสูงกว่า เรียกใช้ 'Update-Module -Name {0} -RequiredVersion {2} -Force' เพื่ออัปเดตเป็นเวอร์ชันที่ต้องการ +'@ diff --git a/AsBuiltReport.Core/Language/th-TH/New-AsBuiltReportConfig.psd1 b/AsBuiltReport.Core/Language/th-TH/New-AsBuiltReportConfig.psd1 new file mode 100644 index 0000000..d67cf8c --- /dev/null +++ b/AsBuiltReport.Core/Language/th-TH/New-AsBuiltReportConfig.psd1 @@ -0,0 +1,11 @@ +# culture = 'th-TH' +ConvertFrom-StringData @' + FolderNotExist = โฟลเดอร์ '{0}' ไม่มีอยู่ โปรดสร้างโฟลเดอร์และเรียกใช้ New-AsBuiltReportConfig อีกครั้ง + ProcessConfig = กำลังประมวลผลไฟล์กำหนดค่ารายงาน {0} จากโมดูล {1} เวอร์ชัน {2} + CopyConfig = กำลังคัดลอกไฟล์กำหนดค่ารายงาน '{0}' ไปยัง '{1}' + CopyModuleConfig = กำลังคัดลอกไฟล์กำหนดค่ารายงาน {0} '{1}' ไปยัง '{2}' + CreateConfig = สร้างไฟล์กำหนดค่ารายงาน {0} '{1}.json' ใน '{2}' แล้ว + OverWriteConfig = กำลังคัดลอกไฟล์กำหนดค่ารายงาน '{0}' ไปยัง '{1}' กำลังเขียนทับไฟล์ที่มีอยู่ + ForceOverwrite = ไฟล์กำหนดค่ารายงาน {0} '{1}.json' มีอยู่แล้วใน '{2}' ใช้ '-Force' เพื่อเขียนทับไฟล์ที่มีอยู่ + ConfigNotFound = ไม่พบไฟล์กำหนดค่ารายงานในเส้นทางโมดูล '{0}' +'@ diff --git a/AsBuiltReport.Core/Language/tr-TR/AsBuiltReportCoreStyle.psd1 b/AsBuiltReport.Core/Language/tr-TR/AsBuiltReportCoreStyle.psd1 new file mode 100644 index 0000000..660d8ba --- /dev/null +++ b/AsBuiltReport.Core/Language/tr-TR/AsBuiltReportCoreStyle.psd1 @@ -0,0 +1,11 @@ +# culture = 'tr-TR' +ConvertFrom-StringData @' + Footer = Sayfa + Logo = AsBuiltReport Logosu + CoverPageWarning = Kapak sayfası resmi görüntülenemiyor. Bu hatayı önlemek için lütfen rapor JSON yapılandırma dosyasında 'ShowCoverPageImage' değerini 'false' olarak ayarlayın. + CoverPage = Kapak Sayfası + Author = Yazar: + Date = Tarih: + Version = Sürüm: + TOC = İçindekiler +'@ diff --git a/AsBuiltReport.Core/Language/tr-TR/New-AsBuiltConfig.psd1 b/AsBuiltReport.Core/Language/tr-TR/New-AsBuiltConfig.psd1 new file mode 100644 index 0000000..58e0e95 --- /dev/null +++ b/AsBuiltReport.Core/Language/tr-TR/New-AsBuiltConfig.psd1 @@ -0,0 +1,58 @@ +# culture = 'tr-TR' +@{ + +# As Built Report Information +ReportInfo = ConvertFrom-StringData @' + BannerTitle = As Built Report Bilgileri + ReportAuthor = Bu As Built Report için yazarın adını girin [{0}] +'@ + +# Company Configuration +CompanyConfig = ConvertFrom-StringData @' + BannerTitle = Şirket Bilgileri + CompanyInfo = As Built Report için şirket bilgilerini girmek ister misiniz? (y/N) + CompanyFullName = Şirketin Tam Adını Girin + CompanyShortName = Şirketin Kısa Adını Girin + CompanyContact = Şirket İletişim Bilgisini Girin + CompanyEmail = Şirket E-posta Adresini Girin + CompanyPhone = Şirket Telefon Numarasını Girin + CompanyAddress = Şirket Adresini Girin +'@ + +# Email Configuration +EmailConfig = ConvertFrom-StringData @' + BannerTitle = E-posta Yapılandırması + ConfigureMailSettings = SMTP yapılandırmasını girmek ister misiniz? (y/N) + MailServer = Posta sunucusu FQDN / IP adresini girin + EmptyMailServerAddress = Posta sunucusu adresi boş olamaz. Lütfen geçerli bir posta sunucusu FQDN / IP adresi girin. + InvalidMailServer = '{0}' geçerli bir FQDN veya IP adresi değil. Lütfen geçerli bir posta sunucusu FQDN / IP adresi girin. + MailServerPort587 = Posta sunucusu port numarasını girin [587] + InvalidMailServerPort587 = Geçersiz port numarası. Lütfen 1 ile 65535 arasında bir sayı girin veya varsayılan değer [587] için Enter tuşuna basın. + MailServerPort25 = Posta sunucusu port numarasını girin [25] + InvalidMailServerPort25 = Geçersiz port numarası. Lütfen 1 ile 65535 arasında bir sayı girin veya varsayılan değer [25] için Enter tuşuna basın. + MailServerUseSSL = Posta sunucusu bağlantısı için SSL kullanılsın mı? (y/N) + MailCredentials = Posta sunucusu kimlik doğrulaması gerekli mi? (y/N) + MailFrom = Gönderici e-posta adresini girin + MailTo = Alıcı e-posta adresini girin + EmptyEmail = E-posta adresi boş olamaz. Lütfen geçerli bir e-posta adresi girin. + InvalidEmail = '{0}' geçerli bir e-posta adresi değil. Lütfen geçerli bir e-posta adresi girin. + AnotherRecipient = Başka bir alıcı girmek istiyor musunuz? (y/N) + MailBodyPrompt = E-posta mesajı gövde içeriğini girin + MailBody = As Built Report eklendi +'@ + +# Report Configuration +ReportConfig = ConvertFrom-StringData @' + BannerTitle = As Built Report Yapılandırması + ReportConfigFolder = Rapor modülü yapılandırma dosyalarını ve özel stil betiklerini saklamak için kullanılacak klasörün tam yolunu girin [{0}] + OverwriteReportConfig = Belirtilen klasörde {0} için bir rapor modülü yapılandırma dosyası zaten var. Üzerine yazmak ister misiniz? (y/N) + CopyFile = '{0}' dosyası '{1}' konumuna kopyalanıyor. + OverwriteFile = '{0}' dosyası '{1}' konumuna kopyalanıyor. Mevcut dosyanın üzerine yazılıyor. + SaveAsBuiltConfig = As Built Report çekirdek modülü yapılandırma dosyasını kaydetmek ister misiniz? (Y/n) + AsBuiltName = As Built Report yapılandırma dosyası için bir ad girin [AsBuiltReport] + AsBuiltExportPath = As Built Report yapılandırma dosyasını kaydetmek için yolu girin [{0}] + ConfigFolder = As Built Report yapılandırma klasörü '{0}' oluşturuluyor. + SaveConfig = As Built Report yapılandırma dosyası '{0}.json' yoluna '{1}' kaydediliyor. + NotSaved = As Built Report yapılandırma dosyası kaydedilmedi. +'@ +} diff --git a/AsBuiltReport.Core/Language/tr-TR/New-AsBuiltReport.psd1 b/AsBuiltReport.Core/Language/tr-TR/New-AsBuiltReport.psd1 new file mode 100644 index 0000000..3da86af --- /dev/null +++ b/AsBuiltReport.Core/Language/tr-TR/New-AsBuiltReport.psd1 @@ -0,0 +1,40 @@ +# culture = 'tr-TR' +ConvertFrom-StringData @' + PwshISE = AsBuiltReport, Windows PowerShell ISE'den çalıştırılamaz. Lütfen bir PowerShell komut penceresi kullanın. + Password = {0} kullanıcısı için parola + OutputFolderPath = OutputFolderPath '{0}' geçerli bir klasör yolu değil. + LoadConfig = As Built Report yapılandırması {0} konumundan yükleniyor. + NoConfigFound = '{0}' yolunda As Built Report yapılandırması bulunamadı. + GeneratingReport = Yeni As Built Report yapılandırması oluşturuluyor. + StyleScriptNotFound = '{0}' yolunda rapor stil betiği bulunamadı. + ReportModuleNotFound = '{1}' yolunda {0} rapor yapılandırma dosyası bulunamadı. + LoadingReportConfig = {0} rapor yapılandırma dosyası '{1}' yolundan yükleniyor. + ReportConfigNotFound = '{0}' modül yolunda rapor yapılandırması bulunamadı. + SetReportFileName = Rapor dosya adı '{0}' olarak ayarlanıyor. + EmailBannerTitle = E-posta Sunucusu Kimlik Bilgileri + EmailCredentials = Lütfen {0} için kimlik bilgilerini girin. + InstalledModule = AsBuiltReport.Core {0} şu anda yüklü. + AvailableModule = AsBuiltReport.Core {0} mevcut. + UpdateModule = En son sürümü yüklemek için 'Update-Module -Name AsBuiltReport.Core -Force' komutunu çalıştırın. + ReportGenerating = Lütfen {0} As Built Report oluşturulurken bekleyin. + ReportInitializing = > Rapor çerçevesi başlatılıyor... + DocumentStyle = > Belge stili yükleniyor... + TargetSystem = > Hedef sisteme bağlanılıyor ve veri toplanıyor... + ExecutionFailed = Rapor modülü yürütme başarısız: {0} + BuildingDocument = > Belge yapısı oluşturuluyor... + ExportingDocument = > Belge dışa aktarılıyor... + Failed = [BAŞARISIZ] Rapor oluşturma başarısız + ReportStyleScript = '{0}' yolundan rapor stil betiği çalıştırılıyor. + InteractiveAuth = Etkileşimli kimlik doğrulama etkinleştirildi. Hedef sisteminize kimlik doğrulaması yapmak için lütfen kimlik doğrulama pencerelerini kontrol edin. + OutputFolder = {0} As Built Report '{1}' şuraya kaydedildi: '{2}'. + ReportModuleInfo1 = Dokümantasyon: https://github.com/AsBuiltReport/AsBuiltReport.{0} + ReportModuleInfo2 = Sorunlar veya hata bildirimi: https://github.com/AsBuiltReport/AsBuiltReport.{0}/issues + ReportModuleInfo3 = Her yeni sürüm yayınlandıktan sonra rapor yapılandırma dosyanızı güncellemeyi unutmayın: https://www.asbuiltreport.com/user-guide/new-asbuiltreportconfig/ + ProjectWebsite = Daha ayrıntılı bilgi için lütfen AsBuiltReport proje web sitesine bakın: https://www.asbuiltreport.com + CommunityProject = AsBuiltReport, topluluk tarafından sürdürülen açık kaynaklı bir projedir. Herhangi bir teknoloji sağlayıcısı, çalışanları veya bağlı kuruluşlarıyla sponsorluğu, onayı veya bağlantısı yoktur. + ReportModuleInstalled = {0} {1} şu anda yüklü. + ReportModuleAvailable = {0} {1} mevcut. + ReportModuleUpdate = En son sürümü yüklemek için 'Update-Module -Name {0} -Force' komutunu çalıştırın. + RequiredModuleNotInstalled = {0} {1} veya daha yüksek sürüm gereklidir. Gerekli modülü yüklemek için 'Install-Module -Name {0} -RequiredVersion {1} -AllowClobber' komutunu çalıştırın. + RequiredModuleTooOld = {0} {1} şu anda yüklü. {0} {2} veya daha yüksek sürüm gereklidir. Gerekli sürüme güncellemek için 'Update-Module -Name {0} -RequiredVersion {2} -Force' komutunu çalıştırın. +'@ diff --git a/AsBuiltReport.Core/Language/tr-TR/New-AsBuiltReportConfig.psd1 b/AsBuiltReport.Core/Language/tr-TR/New-AsBuiltReportConfig.psd1 new file mode 100644 index 0000000..f4ed2f5 --- /dev/null +++ b/AsBuiltReport.Core/Language/tr-TR/New-AsBuiltReportConfig.psd1 @@ -0,0 +1,11 @@ +# culture = 'tr-TR' +ConvertFrom-StringData @' + FolderNotExist = '{0}' klasörü mevcut değil. Lütfen klasörü oluşturun ve New-AsBuiltReportConfig'i tekrar çalıştırın. + ProcessConfig = {1} modülünden, sürüm {2}, {0} rapor yapılandırma dosyası işleniyor. + CopyConfig = Rapor yapılandırma dosyası '{0}' konumuna '{1}' kopyalanıyor. + CopyModuleConfig = {0} rapor yapılandırma dosyası '{1}' konumuna '{2}' kopyalanıyor. + CreateConfig = {0} rapor yapılandırma dosyası '{1}.json' konumunda '{2}' oluşturuldu. + OverWriteConfig = Rapor yapılandırma dosyası '{0}' konumuna '{1}' kopyalanıyor. Mevcut dosyanın üzerine yazılıyor. + ForceOverwrite = {0} rapor yapılandırma dosyası '{1}.json' zaten '{2}' konumunda mevcut. Mevcut dosyanın üzerine yazmak için '-Force' kullanın. + ConfigNotFound = Rapor yapılandırma dosyası modül yolunda '{0}' bulunamadı. +'@ diff --git a/AsBuiltReport.Core/Language/vi-VN/AsBuiltReportCoreStyle.psd1 b/AsBuiltReport.Core/Language/vi-VN/AsBuiltReportCoreStyle.psd1 new file mode 100644 index 0000000..6c6ccfc --- /dev/null +++ b/AsBuiltReport.Core/Language/vi-VN/AsBuiltReportCoreStyle.psd1 @@ -0,0 +1,11 @@ +# culture = 'vi-VN' +ConvertFrom-StringData @' + Footer = Trang + Logo = Logo AsBuiltReport + CoverPageWarning = Không thể hiển thị hình ảnh trang bìa. Vui lòng đặt 'ShowCoverPageImage' thành 'false' trong tệp cấu hình JSON báo cáo để tránh lỗi này. + CoverPage = Trang Bìa + Author = Tác giả: + Date = Ngày: + Version = Phiên bản: + TOC = Mục lục +'@ diff --git a/AsBuiltReport.Core/Language/vi-VN/New-AsBuiltConfig.psd1 b/AsBuiltReport.Core/Language/vi-VN/New-AsBuiltConfig.psd1 new file mode 100644 index 0000000..2d5c7c7 --- /dev/null +++ b/AsBuiltReport.Core/Language/vi-VN/New-AsBuiltConfig.psd1 @@ -0,0 +1,58 @@ +# culture = 'vi-VN' +@{ + +# As Built Report Information +ReportInfo = ConvertFrom-StringData @' + BannerTitle = Thông tin As Built Report + ReportAuthor = Nhập tên tác giả cho As Built Report này [{0}] +'@ + +# Company Configuration +CompanyConfig = ConvertFrom-StringData @' + BannerTitle = Thông tin Công ty + CompanyInfo = Bạn có muốn nhập thông tin công ty cho As Built Report không? (y/N) + CompanyFullName = Nhập Tên Đầy đủ của Công ty + CompanyShortName = Nhập Tên Viết tắt của Công ty + CompanyContact = Nhập Liên hệ Công ty + CompanyEmail = Nhập Địa chỉ Email Công ty + CompanyPhone = Nhập Số Điện thoại Công ty + CompanyAddress = Nhập Địa chỉ Công ty +'@ + +# Email Configuration +EmailConfig = ConvertFrom-StringData @' + BannerTitle = Cấu hình Email + ConfigureMailSettings = Bạn có muốn nhập cấu hình SMTP không? (y/N) + MailServer = Nhập FQDN / địa chỉ IP của máy chủ thư + EmptyMailServerAddress = Địa chỉ máy chủ thư không được để trống. Vui lòng nhập FQDN / địa chỉ IP hợp lệ của máy chủ thư. + InvalidMailServer = '{0}' không phải là FQDN hoặc địa chỉ IP hợp lệ. Vui lòng nhập FQDN / địa chỉ IP hợp lệ của máy chủ thư. + MailServerPort587 = Nhập số cổng máy chủ thư [587] + InvalidMailServerPort587 = Số cổng không hợp lệ. Vui lòng nhập số từ 1 đến 65535 hoặc nhấn Enter cho giá trị mặc định [587]. + MailServerPort25 = Nhập số cổng máy chủ thư [25] + InvalidMailServerPort25 = Số cổng không hợp lệ. Vui lòng nhập số từ 1 đến 65535 hoặc nhấn Enter cho giá trị mặc định [25]. + MailServerUseSSL = Sử dụng SSL cho kết nối máy chủ thư? (y/N) + MailCredentials = Yêu cầu xác thực máy chủ thư? (y/N) + MailFrom = Nhập địa chỉ email người gửi + MailTo = Nhập địa chỉ email người nhận + EmptyEmail = Địa chỉ email không được để trống. Vui lòng nhập địa chỉ email hợp lệ. + InvalidEmail = '{0}' không phải là địa chỉ email hợp lệ. Vui lòng nhập địa chỉ email hợp lệ. + AnotherRecipient = Bạn có muốn nhập người nhận khác không? (y/N) + MailBodyPrompt = Nhập nội dung thông điệp email + MailBody = Đã đính kèm As Built Report +'@ + +# Report Configuration +ReportConfig = ConvertFrom-StringData @' + BannerTitle = Cấu hình As Built Report + ReportConfigFolder = Nhập đường dẫn đầy đủ của thư mục sử dụng để lưu trữ tệp cấu hình mô-đun báo cáo và tập lệnh kiểu tùy chỉnh [{0}] + OverwriteReportConfig = Tệp cấu hình mô-đun báo cáo cho {0} đã tồn tại trong thư mục được chỉ định. Bạn có muốn ghi đè nó không? (y/N) + CopyFile = Đang sao chép '{0}' vào '{1}'. + OverwriteFile = Đang sao chép '{0}' vào '{1}'. Ghi đè tệp hiện có. + SaveAsBuiltConfig = Bạn có muốn lưu tệp cấu hình mô-đun lõi As Built Report không? (Y/n) + AsBuiltName = Nhập tên cho tệp cấu hình As Built Report [AsBuiltReport] + AsBuiltExportPath = Nhập đường dẫn để lưu tệp cấu hình As Built Report [{0}] + ConfigFolder = Đang tạo thư mục cấu hình As Built Report '{0}'. + SaveConfig = Đang lưu tệp cấu hình As Built Report '{0}.json' vào đường dẫn '{1}'. + NotSaved = Tệp cấu hình As Built Report chưa được lưu. +'@ +} diff --git a/AsBuiltReport.Core/Language/vi-VN/New-AsBuiltReport.psd1 b/AsBuiltReport.Core/Language/vi-VN/New-AsBuiltReport.psd1 new file mode 100644 index 0000000..e5ff0a7 --- /dev/null +++ b/AsBuiltReport.Core/Language/vi-VN/New-AsBuiltReport.psd1 @@ -0,0 +1,40 @@ +# culture = 'vi-VN' +ConvertFrom-StringData @' + PwshISE = AsBuiltReport không thể chạy từ Windows PowerShell ISE. Vui lòng sử dụng cửa sổ lệnh PowerShell. + Password = Mật khẩu cho người dùng {0} + OutputFolderPath = OutputFolderPath '{0}' không phải là đường dẫn thư mục hợp lệ. + LoadConfig = Đang tải cấu hình As Built Report từ {0}. + NoConfigFound = Không tìm thấy cấu hình As Built Report trong đường dẫn '{0}'. + GeneratingReport = Đang tạo cấu hình As Built Report mới. + StyleScriptNotFound = Không tìm thấy tập lệnh kiểu báo cáo trong đường dẫn '{0}'. + ReportModuleNotFound = Không tìm thấy tệp cấu hình báo cáo {0} trong đường dẫn '{1}'. + LoadingReportConfig = Đang tải tệp cấu hình báo cáo {0} từ đường dẫn '{1}'. + ReportConfigNotFound = Không tìm thấy cấu hình báo cáo trong đường dẫn mô-đun '{0}'. + SetReportFileName = Đang đặt tên tệp báo cáo thành '{0}'. + EmailBannerTitle = Thông tin đăng nhập máy chủ email + EmailCredentials = Vui lòng nhập thông tin đăng nhập cho {0}. + InstalledModule = AsBuiltReport.Core {0} hiện đang được cài đặt. + AvailableModule = AsBuiltReport.Core {0} đã có sẵn. + UpdateModule = Chạy 'Update-Module -Name AsBuiltReport.Core -Force' để cài đặt phiên bản mới nhất. + ReportGenerating = Vui lòng đợi trong khi báo cáo {0} As Built đang được tạo. + ReportInitializing = > Đang khởi tạo khung báo cáo... + DocumentStyle = > Đang tải kiểu tài liệu... + TargetSystem = > Đang kết nối với hệ thống đích và thu thập dữ liệu... + ExecutionFailed = Thực thi mô-đun báo cáo thất bại: {0} + BuildingDocument = > Đang xây dựng cấu trúc tài liệu... + ExportingDocument = > Đang xuất tài liệu... + Failed = [THẤT BẠI] Tạo báo cáo thất bại + ReportStyleScript = Đang thực thi tập lệnh kiểu báo cáo từ đường dẫn '{0}'. + InteractiveAuth = Xác thực tương tác đã được bật. Vui lòng kiểm tra cửa sổ xác thực để xác thực với hệ thống đích của bạn. + OutputFolder = {0} As Built Report '{1}' đã được lưu vào '{2}'. + ReportModuleInfo1 = Tài liệu: https://github.com/AsBuiltReport/AsBuiltReport.{0} + ReportModuleInfo2 = Vấn đề hoặc báo cáo lỗi: https://github.com/AsBuiltReport/AsBuiltReport.{0}/issues + ReportModuleInfo3 = Đừng quên cập nhật tệp cấu hình báo cáo của bạn sau mỗi lần phát hành phiên bản mới: https://www.asbuiltreport.com/user-guide/new-asbuiltreportconfig/ + ProjectWebsite = Vui lòng tham khảo trang web dự án AsBuiltReport để biết thông tin chi tiết hơn: https://www.asbuiltreport.com + CommunityProject = AsBuiltReport là một dự án mã nguồn mở được cộng đồng duy trì. Nó không có tài trợ, xác nhận hoặc liên kết với bất kỳ nhà cung cấp công nghệ, nhân viên hoặc công ty liên kết nào. + ReportModuleInstalled = {0} {1} hiện đang được cài đặt. + ReportModuleAvailable = {0} {1} đã có sẵn. + ReportModuleUpdate = Chạy 'Update-Module -Name {0} -Force' để cài đặt phiên bản mới nhất. + RequiredModuleNotInstalled = Yêu cầu {0} {1} hoặc cao hơn. Chạy 'Install-Module -Name {0} -RequiredVersion {1} -AllowClobber' để cài đặt mô-đun bắt buộc. + RequiredModuleTooOld = {0} {1} hiện đang được cài đặt. Yêu cầu {0} {2} hoặc cao hơn. Chạy 'Update-Module -Name {0} -RequiredVersion {2} -Force' để cập nhật lên phiên bản bắt buộc. +'@ diff --git a/AsBuiltReport.Core/Language/vi-VN/New-AsBuiltReportConfig.psd1 b/AsBuiltReport.Core/Language/vi-VN/New-AsBuiltReportConfig.psd1 new file mode 100644 index 0000000..699697f --- /dev/null +++ b/AsBuiltReport.Core/Language/vi-VN/New-AsBuiltReportConfig.psd1 @@ -0,0 +1,11 @@ +# culture = 'vi-VN' +ConvertFrom-StringData @' + FolderNotExist = Thư mục '{0}' không tồn tại. Vui lòng tạo thư mục và chạy lại New-AsBuiltReportConfig. + ProcessConfig = Đang xử lý tệp cấu hình báo cáo {0} từ mô-đun {1}, phiên bản {2}. + CopyConfig = Đang sao chép tệp cấu hình báo cáo '{0}' vào '{1}'. + CopyModuleConfig = Đang sao chép tệp cấu hình báo cáo {0} '{1}' vào '{2}'. + CreateConfig = Đã tạo tệp cấu hình báo cáo {0} '{1}.json' trong '{2}'. + OverWriteConfig = Đang sao chép tệp cấu hình báo cáo '{0}' vào '{1}'. Ghi đè tệp hiện có. + ForceOverwrite = Tệp cấu hình báo cáo {0} '{1}.json' đã tồn tại trong '{2}'. Sử dụng '-Force' để ghi đè tệp hiện có. + ConfigNotFound = Không tìm thấy tệp cấu hình báo cáo trong đường dẫn mô-đun '{0}'. +'@ diff --git a/AsBuiltReport.Core/Language/zh-CN/AsBuiltReportCoreStyle.psd1 b/AsBuiltReport.Core/Language/zh-CN/AsBuiltReportCoreStyle.psd1 new file mode 100644 index 0000000..a80770f --- /dev/null +++ b/AsBuiltReport.Core/Language/zh-CN/AsBuiltReportCoreStyle.psd1 @@ -0,0 +1,11 @@ +# culture = 'zh-CN' +ConvertFrom-StringData @' + Footer = 第 页 + Logo = AsBuiltReport 徽标 + CoverPageWarning = 无法显示封面图像。请在报告JSON配置文件中将'ShowCoverPageImage'设置为'false'以避免此错误。 + CoverPage = 封面 + Author = 作者: + Date = 日期: + Version = 版本: + TOC = 目录 +'@ diff --git a/AsBuiltReport.Core/Language/zh-CN/New-AsBuiltConfig.psd1 b/AsBuiltReport.Core/Language/zh-CN/New-AsBuiltConfig.psd1 new file mode 100644 index 0000000..74feed1 --- /dev/null +++ b/AsBuiltReport.Core/Language/zh-CN/New-AsBuiltConfig.psd1 @@ -0,0 +1,58 @@ +# culture = 'zh-CN' +@{ + +# As Built Report Information +ReportInfo = ConvertFrom-StringData @' + BannerTitle = As Built Report 信息 + ReportAuthor = 输入此 As Built Report 的作者姓名 [{0}] +'@ + +# Company Configuration +CompanyConfig = ConvertFrom-StringData @' + BannerTitle = 公司信息 + CompanyInfo = 是否要为 As Built Report 输入公司信息?(y/N) + CompanyFullName = 输入公司全称 + CompanyShortName = 输入公司简称 + CompanyContact = 输入公司联系人 + CompanyEmail = 输入公司电子邮件地址 + CompanyPhone = 输入公司电话号码 + CompanyAddress = 输入公司地址 +'@ + +# Email Configuration +EmailConfig = ConvertFrom-StringData @' + BannerTitle = 电子邮件配置 + ConfigureMailSettings = 是否要输入 SMTP 配置?(y/N) + MailServer = 输入邮件服务器 FQDN / IP 地址 + EmptyMailServerAddress = 邮件服务器地址不能为空。请输入有效的邮件服务器 FQDN / IP 地址。 + InvalidMailServer = '{0}' 不是有效的 FQDN 或 IP 地址。请输入有效的邮件服务器 FQDN / IP 地址。 + MailServerPort587 = 输入邮件服务器端口号 [587] + InvalidMailServerPort587 = 端口号无效。请输入 1 到 65535 之间的数字,或按 Enter 键使用默认值 [587]。 + MailServerPort25 = 输入邮件服务器端口号 [25] + InvalidMailServerPort25 = 端口号无效。请输入 1 到 65535 之间的数字,或按 Enter 键使用默认值 [25]。 + MailServerUseSSL = 是否使用 SSL 连接邮件服务器?(y/N) + MailCredentials = 是否需要邮件服务器身份验证?(y/N) + MailFrom = 输入发件人电子邮件地址 + MailTo = 输入收件人电子邮件地址 + EmptyEmail = 电子邮件地址不能为空。请输入有效的电子邮件地址。 + InvalidEmail = '{0}' 不是有效的电子邮件地址。请输入有效的电子邮件地址。 + AnotherRecipient = 是否要输入其他收件人?(y/N) + MailBodyPrompt = 输入电子邮件正文内容 + MailBody = 已附加 As Built Report +'@ + +# Report Configuration +ReportConfig = ConvertFrom-StringData @' + BannerTitle = As Built Report 配置 + ReportConfigFolder = 输入用于存储报告模块配置文件和自定义样式脚本的文件夹完整路径 [{0}] + OverwriteReportConfig = 指定文件夹中已存在 {0} 的报告模块配置文件。是否要覆盖它?(y/N) + CopyFile = 正在将 '{0}' 复制到 '{1}'。 + OverwriteFile = 正在将 '{0}' 复制到 '{1}'。正在覆盖现有文件。 + SaveAsBuiltConfig = 是否要保存 As Built Report 核心模块配置文件?(Y/n) + AsBuiltName = 输入 As Built Report 配置文件的名称 [AsBuiltReport] + AsBuiltExportPath = 输入保存 As Built Report 配置文件的路径 [{0}] + ConfigFolder = 正在创建 As Built Report 配置文件夹 '{0}'。 + SaveConfig = 正在将 As Built Report 配置文件 '{0}.json' 保存到路径 '{1}'。 + NotSaved = As Built Report 配置文件未保存。 +'@ +} diff --git a/AsBuiltReport.Core/Language/zh-CN/New-AsBuiltReport.psd1 b/AsBuiltReport.Core/Language/zh-CN/New-AsBuiltReport.psd1 new file mode 100644 index 0000000..70bd6df --- /dev/null +++ b/AsBuiltReport.Core/Language/zh-CN/New-AsBuiltReport.psd1 @@ -0,0 +1,40 @@ +# culture = 'zh-CN' +ConvertFrom-StringData @' + PwshISE = AsBuiltReport 无法从 Windows PowerShell ISE 运行。请改用 PowerShell 命令窗口。 + Password = 用户 {0} 的密码 + OutputFolderPath = OutputFolderPath '{0}' 不是有效的文件夹路径。 + LoadConfig = 正在从 {0} 加载 As Built Report 配置。 + NoConfigFound = 在路径 '{0}' 中找不到 As Built Report 配置。 + GeneratingReport = 正在生成新的 As Built Report 配置。 + StyleScriptNotFound = 在路径 '{0}' 中找不到报告样式脚本。 + ReportModuleNotFound = 在路径 '{1}' 中找不到 {0} 报告配置文件。 + LoadingReportConfig = 正在从路径 '{1}' 加载 {0} 报告配置文件。 + ReportConfigNotFound = 在模块路径 '{0}' 中找不到报告配置。 + SetReportFileName = 将报告文件名设置为 '{0}'。 + EmailBannerTitle = 电子邮件服务器凭据 + EmailCredentials = 请输入 {0} 的凭据。 + InstalledModule = AsBuiltReport.Core {0} 当前已安装。 + AvailableModule = AsBuiltReport.Core {0} 可用。 + UpdateModule = 运行 'Update-Module -Name AsBuiltReport.Core -Force' 以安装最新版本。 + ReportGenerating = 请稍候,正在生成 {0} As Built Report。 + ReportInitializing = > 正在初始化报告框架... + DocumentStyle = > 正在加载文档样式... + TargetSystem = > 正在连接到目标系统并收集数据... + ExecutionFailed = 报告模块执行失败:{0} + BuildingDocument = > 正在构建文档结构... + ExportingDocument = > 正在导出文档... + Failed = [失败] 报告生成失败 + ReportStyleScript = 正在从路径 '{0}' 执行报告样式脚本。 + InteractiveAuth = 交互式身份验证已启用。请检查身份验证窗口以对目标系统进行身份验证。 + OutputFolder = {0} As Built Report '{1}' 已保存到 '{2}'。 + ReportModuleInfo1 = 文档: https://github.com/AsBuiltReport/AsBuiltReport.{0} + ReportModuleInfo2 = 问题或错误报告: https://github.com/AsBuiltReport/AsBuiltReport.{0}/issues + ReportModuleInfo3 = 不要忘记在每次新版本发布后更新您的报告配置文件: https://www.asbuiltreport.com/user-guide/new-asbuiltreportconfig/ + ProjectWebsite = 请参阅 AsBuiltReport 项目网站以获取更详细的信息: https://www.asbuiltreport.com + CommunityProject = AsBuiltReport 是一个由社区维护的开源项目。它与任何技术供应商、其员工或附属公司没有赞助、认可或关联。 + ReportModuleInstalled = {0} {1} 当前已安装。 + ReportModuleAvailable = {0} {1} 可用。 + ReportModuleUpdate = 运行 'Update-Module -Name {0} -Force' 以安装最新版本。 + RequiredModuleNotInstalled = 需要 {0} {1} 或更高版本。运行 'Install-Module -Name {0} -RequiredVersion {1} -AllowClobber' 以安装所需的模块。 + RequiredModuleTooOld = {0} {1} 当前已安装。需要 {0} {2} 或更高版本。运行 'Update-Module -Name {0} -RequiredVersion {2} -Force' 以更新到所需版本。 +'@ diff --git a/AsBuiltReport.Core/Language/zh-CN/New-AsBuiltReportConfig.psd1 b/AsBuiltReport.Core/Language/zh-CN/New-AsBuiltReportConfig.psd1 new file mode 100644 index 0000000..3e428f6 --- /dev/null +++ b/AsBuiltReport.Core/Language/zh-CN/New-AsBuiltReportConfig.psd1 @@ -0,0 +1,11 @@ +# culture = 'zh-CN' +ConvertFrom-StringData @' + FolderNotExist = 文件夹 '{0}' 不存在。请创建该文件夹并再次运行 New-AsBuiltReportConfig。 + ProcessConfig = 正在处理模块 {1} 版本 {2} 的 {0} 报告配置文件。 + CopyConfig = 正在将报告配置文件 '{0}' 复制到 '{1}'。 + CopyModuleConfig = 正在将 {0} 报告配置文件 '{1}' 复制到 '{2}'。 + CreateConfig = 已在 '{2}' 中创建 {0} 报告配置文件 '{1}.json'。 + OverWriteConfig = 正在将报告配置文件 '{0}' 复制到 '{1}'。正在覆盖现有文件。 + ForceOverwrite = {0} 报告配置文件 '{1}.json' 已存在于 '{2}' 中。使用 '-Force' 覆盖现有文件。 + ConfigNotFound = 在模块路径 '{0}' 中未找到报告配置文件。 +'@ diff --git a/AsBuiltReport.Core/Language/zh-Hans/AsBuiltReportCoreStyle.psd1 b/AsBuiltReport.Core/Language/zh-Hans/AsBuiltReportCoreStyle.psd1 new file mode 100644 index 0000000..acfa567 --- /dev/null +++ b/AsBuiltReport.Core/Language/zh-Hans/AsBuiltReportCoreStyle.psd1 @@ -0,0 +1,11 @@ +# culture = 'zh-Hans' +ConvertFrom-StringData @' + Footer = 第 页 + Logo = AsBuiltReport 徽标 + CoverPageWarning = 无法显示封面图像。请在报告JSON配置文件中将'ShowCoverPageImage'设置为'false'以避免此错误。 + CoverPage = 封面 + Author = 作者: + Date = 日期: + Version = 版本: + TOC = 目录 +'@ diff --git a/AsBuiltReport.Core/Language/zh-Hans/New-AsBuiltConfig.psd1 b/AsBuiltReport.Core/Language/zh-Hans/New-AsBuiltConfig.psd1 new file mode 100644 index 0000000..0c7ed2e --- /dev/null +++ b/AsBuiltReport.Core/Language/zh-Hans/New-AsBuiltConfig.psd1 @@ -0,0 +1,58 @@ +# culture = 'zh-Hans' +@{ + +# As Built Report Information +ReportInfo = ConvertFrom-StringData @' + BannerTitle = As Built Report 信息 + ReportAuthor = 输入此 As Built Report 的作者姓名 [{0}] +'@ + +# Company Configuration +CompanyConfig = ConvertFrom-StringData @' + BannerTitle = 公司信息 + CompanyInfo = 是否要为 As Built Report 输入公司信息?(y/N) + CompanyFullName = 输入公司全称 + CompanyShortName = 输入公司简称 + CompanyContact = 输入公司联系人 + CompanyEmail = 输入公司电子邮件地址 + CompanyPhone = 输入公司电话号码 + CompanyAddress = 输入公司地址 +'@ + +# Email Configuration +EmailConfig = ConvertFrom-StringData @' + BannerTitle = 电子邮件配置 + ConfigureMailSettings = 是否要输入 SMTP 配置?(y/N) + MailServer = 输入邮件服务器 FQDN / IP 地址 + EmptyMailServerAddress = 邮件服务器地址不能为空。请输入有效的邮件服务器 FQDN / IP 地址。 + InvalidMailServer = '{0}' 不是有效的 FQDN 或 IP 地址。请输入有效的邮件服务器 FQDN / IP 地址。 + MailServerPort587 = 输入邮件服务器端口号 [587] + InvalidMailServerPort587 = 端口号无效。请输入 1 到 65535 之间的数字,或按 Enter 键使用默认值 [587]。 + MailServerPort25 = 输入邮件服务器端口号 [25] + InvalidMailServerPort25 = 端口号无效。请输入 1 到 65535 之间的数字,或按 Enter 键使用默认值 [25]。 + MailServerUseSSL = 是否使用 SSL 连接邮件服务器?(y/N) + MailCredentials = 是否需要邮件服务器身份验证?(y/N) + MailFrom = 输入发件人电子邮件地址 + MailTo = 输入收件人电子邮件地址 + EmptyEmail = 电子邮件地址不能为空。请输入有效的电子邮件地址。 + InvalidEmail = '{0}' 不是有效的电子邮件地址。请输入有效的电子邮件地址。 + AnotherRecipient = 是否要输入其他收件人?(y/N) + MailBodyPrompt = 输入电子邮件正文内容 + MailBody = 已附加 As Built Report +'@ + +# Report Configuration +ReportConfig = ConvertFrom-StringData @' + BannerTitle = As Built Report 配置 + ReportConfigFolder = 输入用于存储报告模块配置文件和自定义样式脚本的文件夹完整路径 [{0}] + OverwriteReportConfig = 指定文件夹中已存在 {0} 的报告模块配置文件。是否要覆盖它?(y/N) + CopyFile = 正在将 '{0}' 复制到 '{1}'。 + OverwriteFile = 正在将 '{0}' 复制到 '{1}'。正在覆盖现有文件。 + SaveAsBuiltConfig = 是否要保存 As Built Report 核心模块配置文件?(Y/n) + AsBuiltName = 输入 As Built Report 配置文件的名称 [AsBuiltReport] + AsBuiltExportPath = 输入保存 As Built Report 配置文件的路径 [{0}] + ConfigFolder = 正在创建 As Built Report 配置文件夹 '{0}'。 + SaveConfig = 正在将 As Built Report 配置文件 '{0}.json' 保存到路径 '{1}'。 + NotSaved = As Built Report 配置文件未保存。 +'@ +} diff --git a/AsBuiltReport.Core/Language/zh-Hans/New-AsBuiltReport.psd1 b/AsBuiltReport.Core/Language/zh-Hans/New-AsBuiltReport.psd1 new file mode 100644 index 0000000..e6b5a21 --- /dev/null +++ b/AsBuiltReport.Core/Language/zh-Hans/New-AsBuiltReport.psd1 @@ -0,0 +1,40 @@ +# culture = 'zh-Hans' +ConvertFrom-StringData @' + PwshISE = AsBuiltReport 无法从 Windows PowerShell ISE 运行。请改用 PowerShell 命令窗口。 + Password = 用户 {0} 的密码 + OutputFolderPath = OutputFolderPath '{0}' 不是有效的文件夹路径。 + LoadConfig = 正在从 {0} 加载 As Built Report 配置。 + NoConfigFound = 在路径 '{0}' 中找不到 As Built Report 配置。 + GeneratingReport = 正在生成新的 As Built Report 配置。 + StyleScriptNotFound = 在路径 '{0}' 中找不到报告样式脚本。 + ReportModuleNotFound = 在路径 '{1}' 中找不到 {0} 报告配置文件。 + LoadingReportConfig = 正在从路径 '{1}' 加载 {0} 报告配置文件。 + ReportConfigNotFound = 在模块路径 '{0}' 中找不到报告配置。 + SetReportFileName = 将报告文件名设置为 '{0}'。 + EmailBannerTitle = 电子邮件服务器凭据 + EmailCredentials = 请输入 {0} 的凭据。 + InstalledModule = AsBuiltReport.Core {0} 当前已安装。 + AvailableModule = AsBuiltReport.Core {0} 可用。 + UpdateModule = 运行 'Update-Module -Name AsBuiltReport.Core -Force' 以安装最新版本。 + ReportGenerating = 请稍候,正在生成 {0} As Built Report。 + ReportInitializing = > 正在初始化报告框架... + DocumentStyle = > 正在加载文档样式... + TargetSystem = > 正在连接到目标系统并收集数据... + ExecutionFailed = 报告模块执行失败:{0} + BuildingDocument = > 正在构建文档结构... + ExportingDocument = > 正在导出文档... + Failed = [失败] 报告生成失败 + ReportStyleScript = 正在从路径 '{0}' 执行报告样式脚本。 + InteractiveAuth = 交互式身份验证已启用。请检查身份验证窗口以对目标系统进行身份验证。 + OutputFolder = {0} As Built Report '{1}' 已保存到 '{2}'。 + ReportModuleInfo1 = 文档: https://github.com/AsBuiltReport/AsBuiltReport.{0} + ReportModuleInfo2 = 问题或错误报告: https://github.com/AsBuiltReport/AsBuiltReport.{0}/issues + ReportModuleInfo3 = 不要忘记在每次新版本发布后更新您的报告配置文件: https://www.asbuiltreport.com/user-guide/new-asbuiltreportconfig/ + ProjectWebsite = 请参阅 AsBuiltReport 项目网站以获取更详细的信息: https://www.asbuiltreport.com + CommunityProject = AsBuiltReport 是一个由社区维护的开源项目。它与任何技术供应商、其员工或附属公司没有赞助、认可或关联。 + ReportModuleInstalled = {0} {1} 当前已安装。 + ReportModuleAvailable = {0} {1} 可用。 + ReportModuleUpdate = 运行 'Update-Module -Name {0} -Force' 以安装最新版本。 + RequiredModuleNotInstalled = 需要 {0} {1} 或更高版本。运行 'Install-Module -Name {0} -RequiredVersion {1} -AllowClobber' 以安装所需的模块。 + RequiredModuleTooOld = {0} {1} 当前已安装。需要 {0} {2} 或更高版本。运行 'Update-Module -Name {0} -RequiredVersion {2} -Force' 以更新到所需版本。 +'@ diff --git a/AsBuiltReport.Core/Language/zh-Hans/New-AsBuiltReportConfig.psd1 b/AsBuiltReport.Core/Language/zh-Hans/New-AsBuiltReportConfig.psd1 new file mode 100644 index 0000000..372b4f0 --- /dev/null +++ b/AsBuiltReport.Core/Language/zh-Hans/New-AsBuiltReportConfig.psd1 @@ -0,0 +1,11 @@ +# culture = 'zh-Hans' +ConvertFrom-StringData @' + FolderNotExist = 文件夹 '{0}' 不存在。请创建该文件夹并再次运行 New-AsBuiltReportConfig。 + ProcessConfig = 正在处理模块 {1} 版本 {2} 的 {0} 报告配置文件。 + CopyConfig = 正在将报告配置文件 '{0}' 复制到 '{1}'。 + CopyModuleConfig = 正在将 {0} 报告配置文件 '{1}' 复制到 '{2}'。 + CreateConfig = 已在 '{2}' 中创建 {0} 报告配置文件 '{1}.json'。 + OverWriteConfig = 正在将报告配置文件 '{0}' 复制到 '{1}'。正在覆盖现有文件。 + ForceOverwrite = {0} 报告配置文件 '{1}.json' 已存在于 '{2}' 中。使用 '-Force' 覆盖现有文件。 + ConfigNotFound = 在模块路径 '{0}' 中未找到报告配置文件。 +'@ diff --git a/AsBuiltReport.Core/Language/zh-Hant/AsBuiltReportCoreStyle.psd1 b/AsBuiltReport.Core/Language/zh-Hant/AsBuiltReportCoreStyle.psd1 new file mode 100644 index 0000000..8064af7 --- /dev/null +++ b/AsBuiltReport.Core/Language/zh-Hant/AsBuiltReportCoreStyle.psd1 @@ -0,0 +1,11 @@ +# culture = 'zh-Hant' +ConvertFrom-StringData @' + Footer = 第 頁 + Logo = AsBuiltReport 徽標 + CoverPageWarning = 無法顯示封面圖像。請在報告JSON配置檔案中將'ShowCoverPageImage'設定為'false'以避免此錯誤。 + CoverPage = 封面 + Author = 作者: + Date = 日期: + Version = 版本: + TOC = 目錄 +'@ diff --git a/AsBuiltReport.Core/Language/zh-Hant/New-AsBuiltConfig.psd1 b/AsBuiltReport.Core/Language/zh-Hant/New-AsBuiltConfig.psd1 new file mode 100644 index 0000000..2fa776a --- /dev/null +++ b/AsBuiltReport.Core/Language/zh-Hant/New-AsBuiltConfig.psd1 @@ -0,0 +1,58 @@ +# culture = 'zh-Hant' +@{ + +# As Built Report Information +ReportInfo = ConvertFrom-StringData @' + BannerTitle = As Built Report 資訊 + ReportAuthor = 輸入此 As Built Report 的作者姓名 [{0}] +'@ + +# Company Configuration +CompanyConfig = ConvertFrom-StringData @' + BannerTitle = 公司資訊 + CompanyInfo = 是否要為 As Built Report 輸入公司資訊?(y/N) + CompanyFullName = 輸入公司全稱 + CompanyShortName = 輸入公司簡稱 + CompanyContact = 輸入公司聯絡人 + CompanyEmail = 輸入公司電子郵件地址 + CompanyPhone = 輸入公司電話號碼 + CompanyAddress = 輸入公司地址 +'@ + +# Email Configuration +EmailConfig = ConvertFrom-StringData @' + BannerTitle = 電子郵件設定 + ConfigureMailSettings = 是否要輸入 SMTP 設定?(y/N) + MailServer = 輸入郵件伺服器 FQDN / IP 地址 + EmptyMailServerAddress = 郵件伺服器地址不能為空。請輸入有效的郵件伺服器 FQDN / IP 地址。 + InvalidMailServer = '{0}' 不是有效的 FQDN 或 IP 地址。請輸入有效的郵件伺服器 FQDN / IP 地址。 + MailServerPort587 = 輸入郵件伺服器連接埠號 [587] + InvalidMailServerPort587 = 連接埠號無效。請輸入 1 到 65535 之間的數字,或按 Enter 鍵使用預設值 [587]。 + MailServerPort25 = 輸入郵件伺服器連接埠號 [25] + InvalidMailServerPort25 = 連接埠號無效。請輸入 1 到 65535 之間的數字,或按 Enter 鍵使用預設值 [25]。 + MailServerUseSSL = 是否使用 SSL 連接郵件伺服器?(y/N) + MailCredentials = 是否需要郵件伺服器身份驗證?(y/N) + MailFrom = 輸入寄件人電子郵件地址 + MailTo = 輸入收件人電子郵件地址 + EmptyEmail = 電子郵件地址不能為空。請輸入有效的電子郵件地址。 + InvalidEmail = '{0}' 不是有效的電子郵件地址。請輸入有效的電子郵件地址。 + AnotherRecipient = 是否要輸入其他收件人?(y/N) + MailBodyPrompt = 輸入電子郵件正文內容 + MailBody = 已附加 As Built Report +'@ + +# Report Configuration +ReportConfig = ConvertFrom-StringData @' + BannerTitle = As Built Report 設定 + ReportConfigFolder = 輸入用於儲存報告模組設定檔案和自訂樣式指令碼的資料夾完整路徑 [{0}] + OverwriteReportConfig = 指定資料夾中已存在 {0} 的報告模組設定檔案。是否要覆寫它?(y/N) + CopyFile = 正在將 '{0}' 複製到 '{1}'。 + OverwriteFile = 正在將 '{0}' 複製到 '{1}'。正在覆寫現有檔案。 + SaveAsBuiltConfig = 是否要儲存 As Built Report 核心模組設定檔案?(Y/n) + AsBuiltName = 輸入 As Built Report 設定檔案的名稱 [AsBuiltReport] + AsBuiltExportPath = 輸入儲存 As Built Report 設定檔案的路徑 [{0}] + ConfigFolder = 正在建立 As Built Report 設定資料夾 '{0}'。 + SaveConfig = 正在將 As Built Report 設定檔案 '{0}.json' 儲存到路徑 '{1}'。 + NotSaved = As Built Report 設定檔案未儲存。 +'@ +} diff --git a/AsBuiltReport.Core/Language/zh-Hant/New-AsBuiltReport.psd1 b/AsBuiltReport.Core/Language/zh-Hant/New-AsBuiltReport.psd1 new file mode 100644 index 0000000..dc6f486 --- /dev/null +++ b/AsBuiltReport.Core/Language/zh-Hant/New-AsBuiltReport.psd1 @@ -0,0 +1,40 @@ +# culture = 'zh-Hant' +ConvertFrom-StringData @' + PwshISE = AsBuiltReport 無法從 Windows PowerShell ISE 執行。請改用 PowerShell 命令視窗。 + Password = 使用者 {0} 的密碼 + OutputFolderPath = OutputFolderPath '{0}' 不是有效的資料夾路徑。 + LoadConfig = 正在從 {0} 載入 As Built Report 組態。 + NoConfigFound = 在路徑 '{0}' 中找不到 As Built Report 組態。 + GeneratingReport = 正在產生新的 As Built Report 組態。 + StyleScriptNotFound = 在路徑 '{0}' 中找不到報告樣式指令碼。 + ReportModuleNotFound = 在路徑 '{1}' 中找不到 {0} 報告組態檔。 + LoadingReportConfig = 正在從路徑 '{1}' 載入 {0} 報告組態檔。 + ReportConfigNotFound = 在模組路徑 '{0}' 中找不到報告組態。 + SetReportFileName = 將報告檔案名稱設定為 '{0}'。 + EmailBannerTitle = 電子郵件伺服器認證 + EmailCredentials = 請輸入 {0} 的認證。 + InstalledModule = AsBuiltReport.Core {0} 目前已安裝。 + AvailableModule = AsBuiltReport.Core {0} 可用。 + UpdateModule = 執行 'Update-Module -Name AsBuiltReport.Core -Force' 以安裝最新版本。 + ReportGenerating = 請稍候,正在產生 {0} As Built Report。 + ReportInitializing = > 正在初始化報告框架... + DocumentStyle = > 正在載入文件樣式... + TargetSystem = > 正在連線到目標系統並收集資料... + ExecutionFailed = 報告模組執行失敗:{0} + BuildingDocument = > 正在建立文件結構... + ExportingDocument = > 正在匯出文件... + Failed = [失敗] 報告產生失敗 + ReportStyleScript = 正在從路徑 '{0}' 執行報告樣式指令碼。 + InteractiveAuth = 互動式驗證已啟用。請檢查驗證視窗以對目標系統進行驗證。 + OutputFolder = {0} As Built Report '{1}' 已儲存至 '{2}'。 + ReportModuleInfo1 = 文件: https://github.com/AsBuiltReport/AsBuiltReport.{0} + ReportModuleInfo2 = 問題或錯誤報告: https://github.com/AsBuiltReport/AsBuiltReport.{0}/issues + ReportModuleInfo3 = 不要忘記在每次新版本發佈後更新您的報告組態檔: https://www.asbuiltreport.com/user-guide/new-asbuiltreportconfig/ + ProjectWebsite = 請參閱 AsBuiltReport 專案網站以取得更詳細的資訊: https://www.asbuiltreport.com + CommunityProject = AsBuiltReport 是一個由社群維護的開放原始碼專案。它與任何技術供應商、其員工或關聯公司沒有贊助、認可或關聯。 + ReportModuleInstalled = {0} {1} 目前已安裝。 + ReportModuleAvailable = {0} {1} 可用。 + ReportModuleUpdate = 執行 'Update-Module -Name {0} -Force' 以安裝最新版本。 + RequiredModuleNotInstalled = 需要 {0} {1} 或更高版本。執行 'Install-Module -Name {0} -RequiredVersion {1} -AllowClobber' 以安裝所需的模組。 + RequiredModuleTooOld = {0} {1} 目前已安裝。需要 {0} {2} 或更高版本。執行 'Update-Module -Name {0} -RequiredVersion {2} -Force' 以更新至所需版本。 +'@ diff --git a/AsBuiltReport.Core/Language/zh-Hant/New-AsBuiltReportConfig.psd1 b/AsBuiltReport.Core/Language/zh-Hant/New-AsBuiltReportConfig.psd1 new file mode 100644 index 0000000..1adc85c --- /dev/null +++ b/AsBuiltReport.Core/Language/zh-Hant/New-AsBuiltReportConfig.psd1 @@ -0,0 +1,11 @@ +# culture = 'zh-Hant' +ConvertFrom-StringData @' + FolderNotExist = 資料夾 '{0}' 不存在。請建立該資料夾並再次執行 New-AsBuiltReportConfig。 + ProcessConfig = 正在處理模組 {1} 版本 {2} 的 {0} 報告設定檔案。 + CopyConfig = 正在將報告設定檔案 '{0}' 複製到 '{1}'。 + CopyModuleConfig = 正在將 {0} 報告設定檔案 '{1}' 複製到 '{2}'。 + CreateConfig = 已在 '{2}' 中建立 {0} 報告設定檔案 '{1}.json'。 + OverWriteConfig = 正在將報告設定檔案 '{0}' 複製到 '{1}'。正在覆寫現有檔案。 + ForceOverwrite = {0} 報告設定檔案 '{1}.json' 已存在於 '{2}' 中。使用 '-Force' 覆寫現有檔案。 + ConfigNotFound = 在模組路徑 '{0}' 中未找到報告設定檔案。 +'@ diff --git a/AsBuiltReport.Core/Src/Private/Draw-AsciiBanner.ps1 b/AsBuiltReport.Core/Src/Private/Draw-AsciiBanner.ps1 new file mode 100644 index 0000000..1df776e --- /dev/null +++ b/AsBuiltReport.Core/Src/Private/Draw-AsciiBanner.ps1 @@ -0,0 +1,50 @@ +function Draw-AsciiBanner { + <# + .SYNOPSIS + Draws a decorative banner with text for console output. + .DESCRIPTION + Draws a simple banner with horizontal line separators above and below text. + Uses Unicode characters for a clean appearance that works reliably across all + languages, scripts, and terminal types. + .PARAMETER Lines + An array of strings to display in the banner. Each string will be displayed on its own line. + .PARAMETER TextColor + The color to use for the text content. Accepts standard PowerShell console colors. + .PARAMETER SeparatorColor + The color to use for the separator lines. Accepts standard PowerShell console colors. + .PARAMETER SeparatorLength + The length of the separator lines. Default is 60 characters. + .EXAMPLE + Draw-AsciiBanner -Lines @("Welcome", "AsBuiltReport") -TextColor 'Cyan' -SeparatorColor 'Cyan' + + Displays a cyan-colored banner with "Welcome" and "AsBuiltReport" on separate lines. + .EXAMPLE + Draw-AsciiBanner -Lines @("Configuration") -TextColor 'Green' -SeparatorColor 'Yellow' + + Displays a banner with green text and yellow separator lines. + .NOTES + This is a private function used internally by the AsBuiltReport.Core module. + Uses a simple horizontal line format that works reliably with all character sets. + #> + param( + [string[]]$Lines, + [string]$TextColor, + [string]$SeparatorColor, + [int]$SeparatorLength = 60 + ) + + # Use heavy horizontal line character for visual separation + $separator = [char]0x2500 # ─ + $separatorLine = $separator.ToString() * $SeparatorLength + + # Draw top separator + Write-Host $separatorLine -ForegroundColor $SeparatorColor + + # Draw each line of text with padding + foreach ($line in $Lines) { + Write-Host " $line" -ForegroundColor $TextColor + } + + # Draw bottom separator + Write-Host $separatorLine -ForegroundColor $SeparatorColor +} diff --git a/AsBuiltReport.Core/Src/Private/Get-RequiredModule.ps1 b/AsBuiltReport.Core/Src/Private/Get-RequiredModule.ps1 new file mode 100644 index 0000000..c57d1cc --- /dev/null +++ b/AsBuiltReport.Core/Src/Private/Get-RequiredModule.ps1 @@ -0,0 +1,63 @@ +function Get-RequiredModule { + <# + .SYNOPSIS + Checks if the required version of a PowerShell module is installed. + + .DESCRIPTION + This function verifies that a specified PowerShell module is installed with the required + minimum version. If the module is not installed or the version is too old, it throws an + error with instructions on how to install or update the module. + + .PARAMETER Name + The name of the required PowerShell module (e.g., 'Az', 'VMware.PowerCLI'). + + .PARAMETER Version + The minimum required version of the PowerShell module (e.g., '14.2.0'). + + .EXAMPLE + Get-RequiredModule -Name 'Az' -Version '14.2.0' + + Checks if Azure PowerShell module version 14.2.0 or higher is installed. + + .EXAMPLE + Get-RequiredModule -Name 'VMware.PowerCLI' -Version '13.0.0' + + Checks if VMware PowerCLI version 13.0.0 or higher is installed. + + .NOTES + This function uses the global $translate variable for localized error messages. + Throws an error if the module is not installed or version is too old. + #> + + [CmdletBinding()] + param ( + [Parameter(Mandatory = $true, ValueFromPipeline = $false)] + [ValidateNotNullOrEmpty()] + [String] $Name, + + [Parameter(Mandatory = $true, ValueFromPipeline = $false)] + [ValidateNotNullOrEmpty()] + [String] $Version + ) + + # Check if the required version of the module is installed + $RequiredModule = Get-Module -ListAvailable -Name $Name | + Sort-Object -Property Version -Descending | + Select-Object -First 1 + + if ($RequiredModule) { + $ModuleVersion = "$($RequiredModule.Version.Major)" + "." + "$($RequiredModule.Version.Minor)" + "." + "$($RequiredModule.Version.Build)" + } else { + $ModuleVersion = $null + } + + # Module not installed + if (-not $ModuleVersion -or $ModuleVersion -eq ".") { + throw ($translate.RequiredModuleNotInstalled -f $Name, $Version) + } + + # Module version too old + if ([Version]$ModuleVersion -lt [Version]$Version) { + throw ($translate.RequiredModuleTooOld -f $Name, $ModuleVersion, $Version) + } +} diff --git a/AsBuiltReport.Core/Src/Private/Initialize-LocalizedData.ps1 b/AsBuiltReport.Core/Src/Private/Initialize-LocalizedData.ps1 new file mode 100644 index 0000000..461043d --- /dev/null +++ b/AsBuiltReport.Core/Src/Private/Initialize-LocalizedData.ps1 @@ -0,0 +1,263 @@ +function Initialize-LocalizedData { + <# + .SYNOPSIS + Initializes localized data for AsBuiltReport Core and Report modules. + + .DESCRIPTION + This function loads localized strings from language files (.psd1) based on the specified or detected culture. + It supports both Core and Report modules with intelligent fallback logic: + + For Core modules (when no Language parameter specified): + - Uses the user's OS language (Get-Culture) + - Searches the Core module's Language folder with culture fallback + + For Report modules (when no Language parameter specified): + - Defaults to en-US + - Searches the Report module's Language folder with culture fallback + - Falls back to the Core module's Language folder for shared translations + + When Language parameter is explicitly provided: + - Uses the specified language for both Core and Report modules + + Language selection priority for Report modules: + 1. ReportLanguage parameter (if explicitly specified by user) + 2. Report.Language setting from JSON configuration file + 3. Default fallback to 'en-US' + + .PARAMETER ModuleBasePath + The base path of the module containing the Language folder. + This should point to the module's root directory where the Language subfolder is located. + + .PARAMETER LanguageFile + The name of the language file (without .psd1 extension). + + .PARAMETER ModuleType + The type of module: 'Core' or 'Report'. Defaults to 'Core'. + + .PARAMETER ModuleName + The name of the report module (e.g., 'VMware.vSphere'). + Used for Report modules to help identify the module context. + + .PARAMETER Language + The specific language to use (e.g., 'en-US', 'es-ES', 'fr-FR'). + If not specified: + - Core modules use the user's OS language + - Report modules default to 'en-US' + + .EXAMPLE + # Core module usage - uses OS language + Initialize-LocalizedData -ModuleBasePath $PSScriptRoot -LanguageFile 'New-AsBuiltReport' -ModuleType 'Core' + + .EXAMPLE + # Core module usage with explicit language + Initialize-LocalizedData -ModuleBasePath $PSScriptRoot -LanguageFile 'New-AsBuiltReport' -ModuleType 'Core' -Language 'fr-FR' + + .EXAMPLE + # Report module usage - defaults to en-US + Initialize-LocalizedData -ModuleBasePath $PSScriptRoot -LanguageFile 'VMwareSphere' -ModuleType 'Report' -ModuleName 'VMware.vSphere' + + .EXAMPLE + # Report module usage with explicit language + Initialize-LocalizedData -ModuleBasePath $PSScriptRoot -LanguageFile 'VMwareSphere' -ModuleType 'Report' -ModuleName 'VMware.vSphere' -Language 'es-ES' + + .NOTES + Sets global variable $global:translate with the loaded translations. + Uses Resolve-Culture function for comprehensive culture fallback. + #> + [CmdletBinding()] + param( + [Parameter(Mandatory = $true)] + [string]$ModuleBasePath, + + [Parameter(Mandatory = $true)] + [string]$LanguageFile, + + [Parameter()] + [ValidateSet('Core', 'Report')] + [string]$ModuleType = 'Core', + + [Parameter()] + [string]$ModuleName, + + [Parameter()] + [string]$Language + ) + + try { + # Determine which language to use based on parameters and module type + if ($Language) { + # Explicit language parameter provided + $Culture = [System.Globalization.CultureInfo]::GetCultureInfo($Language) + } elseif ($ModuleType -eq 'Core') { + # For Core modules, use the user's OS language + $Culture = Get-Culture + } else { + # For Report modules without explicit language, use en-US as default + $Culture = [System.Globalization.CultureInfo]::GetCultureInfo('en-US') + } + $PSDefaultParameterValues['*:UICulture'] = $Culture.Name + $PSDefaultParameterValues['*:Culture'] = $Culture.Name + } catch { + Write-Error ($_.Exception.Message) + return + } + + # Setup all paths required for script to run + $script:RootPath = $ModuleBasePath + + # Define search paths based on module type + $SearchPaths = @() + if ($ModuleType -eq 'Report' -and $ModuleName) { + # For report modules, search report module first, then core module + $ReportLangPath = Join-Path $RootPath 'Language' + $SearchPaths += @{Path = $ReportLangPath; Type = 'Report'} + + # Try to find Core module path for fallback + try { + $CoreModule = Get-Module -Name 'AsBuiltReport.Core' -ListAvailable | Sort-Object -Property Version -Descending | Select-Object -First 1 + if ($CoreModule) { + $CoreLangPath = Join-Path $CoreModule.ModuleBase 'Language' + $SearchPaths += @{Path = $CoreLangPath; Type = 'Core'} + } + } catch { + Write-Warning "Could not locate AsBuiltReport.Core module for fallback translations" + } + } else { + # For core modules, use the existing logic + $script:LangPath = Join-Path $RootPath 'Language' + $SearchPaths += @{Path = $script:LangPath; Type = 'Core'} + } + + # Get fallback chain for current culture + $CultureFallbacks = Resolve-Culture -CultureName $Culture.Name + + # Find first available culture where BOTH folder AND file exist + $TargetCulture = $null + $Translate = $null + $FoundPath = $null + + # Search through all search paths and culture fallbacks + foreach ($SearchPath in $SearchPaths) { + foreach ($FallbackCulture in $CultureFallbacks) { + $TestPath = Join-Path $SearchPath.Path $FallbackCulture + $TestFile = Join-Path $TestPath "$LanguageFile.psd1" + if ((Test-Path $TestPath) -and (Test-Path $TestFile)) { + try { + # Test if the file can actually be imported + $TestImport = Import-LocalizedData -BaseDirectory $SearchPath.Path -UICulture $FallbackCulture -FileName $LanguageFile -ErrorAction Stop + $TargetCulture = $FallbackCulture + $Translate = $TestImport + $FoundPath = $SearchPath.Path + $script:LangPath = $SearchPath.Path + break + } catch { + # Preserve the actual error details and continue to next fallback if import fails + $ErrorDetails = "Cannot load $FallbackCulture language file from '$TestFile'. Error: $($_.Exception.Message)" + Write-Error $ErrorDetails -ErrorAction Stop + } + } + } + # If we found a translation, break out of search paths loop + if ($TargetCulture) { break } + } + + # Final safety net - try en-US if nothing else worked + if (-not $TargetCulture -or -not $Translate) { + foreach ($SearchPath in $SearchPaths) { + $TestPath = Join-Path $SearchPath.Path 'en-US' + $TestFile = Join-Path $TestPath "$LanguageFile.psd1" + + if ((Test-Path $TestPath) -and (Test-Path $TestFile)) { + try { + $Translate = Import-LocalizedData -BaseDirectory $SearchPath.Path -UICulture 'en-US' -FileName $LanguageFile -ErrorAction Stop + $TargetCulture = 'en-US' + $FoundPath = $SearchPath.Path + $script:LangPath = $SearchPath.Path + break + } catch { + $ErrorDetails = "Cannot load en-US language file from '$TestFile'. Error: $($_.Exception.Message)" + Write-Error $ErrorDetails -ErrorAction Stop + } + } + } + + # If still no translation found, error out + if (-not $TargetCulture -or -not $Translate) { + $SearchedPaths = ($SearchPaths | ForEach-Object { Join-Path $_.Path "en-US\$LanguageFile.psd1" }) -join ', ' + Write-Error "en-US language file not found in any of the searched paths: $SearchedPaths" -ErrorAction Stop + } + } + + $script:CulturePath = Join-Path $script:LangPath $TargetCulture + + # Output appropriate message (only once per session per culture/module combination) + # Determine the source of the translations + $SourceType = $null + foreach ($SearchPath in $SearchPaths) { + if ($SearchPath.Path -eq $FoundPath) { + $SourceType = $SearchPath.Type + break + } + } + + # Determine the appropriate message based on module type + # Core module = UI language, Report module = Document language + $LanguageType = if ($ModuleType -eq 'Core') { "UI language" } else { "document language" } + + + # Determine the language source for Report modules + $LanguageSourceText = "" + if ($ModuleType -eq 'Report' -and $Language) { + # Check if the language was explicitly specified via command-line parameter + # by examining if ReportConfig exists and comparing with its language setting + if ($global:ReportConfig -and $global:ReportConfig.Report.Language) { + if ($Language -eq $global:ReportConfig.Report.Language) { + $LanguageSourceText = " (from report configuration file)" + } else { + # Language differs from config, so it must be from command-line + $LanguageSourceText = " (from command-line parameter)" + } + } elseif ($Language -eq 'en-US') { + # Default language + $LanguageSourceText = " (fallback to default)" + } else { + # Explicitly specified via command-line (no config or config doesn't have language) + $LanguageSourceText = " (from command-line parameter)" + } + } + # Create unique key for this culture fallback scenario + # When there's a fallback, include module type to show both messages + # When there's no fallback, just use culture to avoid duplicate messages for same culture + if ($TargetCulture -ne $Culture.Name) { + $LocalizationKey = "$TargetCulture-$($Culture.Name)-$ModuleType" + } else { + $LocalizationKey = "$TargetCulture" + } + + # Initialize global tracking variable if it doesn't exist + if (-not $global:AsBuiltReportLocalizedWarnings) { + $global:AsBuiltReportLocalizedWarnings = @{} + } + + # Only show message if we haven't shown it before for this combination + $ShouldShowMessage = -not $global:AsBuiltReportLocalizedWarnings.ContainsKey($LocalizationKey) + + # Suppress messages for style-related language files (internal implementation detail) + if ($LanguageFile -eq 'AsBuiltReportCoreStyle') { + $ShouldShowMessage = $false + } + + if ($ShouldShowMessage) { + if ($TargetCulture -ne $Culture.Name) { + Write-Host ("Setting $LanguageType to '{0}' (fallback from '{1}')$LanguageSourceText." -f $TargetCulture, $Culture.Name) -ForegroundColor Yellow + } else { + Write-Host ("Setting $LanguageType to '{0}'$LanguageSourceText." -f $TargetCulture) -ForegroundColor Yellow + } + + # Mark this combination as already shown + $global:AsBuiltReportLocalizedWarnings[$LocalizationKey] = $true + } + + # Set as global variable + $global:translate = $Translate +} \ No newline at end of file diff --git a/AsBuiltReport.Core/Src/Private/Resolve-Culture.ps1 b/AsBuiltReport.Core/Src/Private/Resolve-Culture.ps1 new file mode 100644 index 0000000..e2f54ff --- /dev/null +++ b/AsBuiltReport.Core/Src/Private/Resolve-Culture.ps1 @@ -0,0 +1,220 @@ +# Function to resolve culture with fallback +function Resolve-Culture { + <# + .SYNOPSIS + Resolves a culture name to a fallback chain of culture names. + .DESCRIPTION + Returns an array of culture names representing the fallback chain for a given culture. + The function provides intelligent fallbacks for regional language variants. + + For example, 'fr-CA' (French-Canada) will fall back to 'fr-FR' (French-France), then 'en-US'. + This ensures that if a specific regional translation is not available, the function will try + the parent language, and finally fall back to en-US. + + The function includes comprehensive mappings for: + - English variants (en-AU, en-GB, en-CA, etc.) + - Chinese variants (simplified and traditional) + - French, Spanish, German, Italian variants + - Japanese, Korean, Arabic, and many other languages + .PARAMETER CultureName + The culture name to resolve (e.g., 'en-US', 'fr-CA', 'zh-CN'). + .OUTPUTS + System.String[] + Returns an array of culture names in fallback order. + .EXAMPLE + Resolve-Culture -CultureName 'fr-CA' + + Returns: @('fr-CA', 'fr-FR', 'en-US') + .EXAMPLE + Resolve-Culture -CultureName 'en-AU' + + Returns: @('en-AU', 'en-GB', 'en-US') + .EXAMPLE + Resolve-Culture -CultureName 'es-MX' + + Returns: @('es-MX', 'es-ES', 'en-US') + .NOTES + This is a private function used internally by Initialize-LocalizedData. + Supports over 60 culture variants with intelligent fallback chains. + If a culture is not explicitly mapped, the function will attempt to fall back to + the parent language family (e.g., 'de-XX' -> 'de-DE' -> 'en-US'). + #> + param([string]$CultureName) + + # Define culture mapping with fallback chain + $CultureMappings = @{ + # English variants + 'en-AU' = @('en-AU', 'en-GB', 'en-US') + 'en-CA' = @('en-CA', 'en-GB', 'en-US') + 'en-IE' = @('en-IE', 'en-GB', 'en-US') + 'en-IN' = @('en-IN', 'en-GB', 'en-US') + 'en-NZ' = @('en-NZ', 'en-GB', 'en-US') + 'en-SG' = @('en-SG', 'en-GB', 'en-US') + 'en-ZA' = @('en-ZA', 'en-GB', 'en-US') + 'en-GB' = @('en-GB', 'en-US') + 'en-US' = @('en-US') + + # Chinese variants + 'zh-CN' = @('zh-CN', 'zh-Hans', 'en-US') # Simplified Chinese (China) + 'zh-TW' = @('zh-TW', 'zh-Hant', 'en-US') # Traditional Chinese (Taiwan) + 'zh-HK' = @('zh-HK', 'zh-Hant', 'zh-TW', 'en-US') # Chinese (Hong Kong) + 'zh-SG' = @('zh-SG', 'zh-Hans', 'zh-CN', 'en-US') # Chinese (Singapore) + 'zh-MO' = @('zh-MO', 'zh-Hant', 'zh-HK', 'en-US') # Chinese (Macau) + 'zh-Hans' = @('zh-Hans', 'zh-CN', 'en-US') # Simplified Chinese + 'zh-Hant' = @('zh-Hant', 'zh-TW', 'en-US') # Traditional Chinese + + # French variants + 'fr-FR' = @('fr-FR', 'en-US') # French (France) + 'fr-CA' = @('fr-CA', 'fr-FR', 'en-US') # French (Canada) + 'fr-BE' = @('fr-BE', 'fr-FR', 'en-US') # French (Belgium) + 'fr-CH' = @('fr-CH', 'fr-FR', 'en-US') # French (Switzerland) + 'fr-LU' = @('fr-LU', 'fr-FR', 'en-US') # French (Luxembourg) + 'fr-MC' = @('fr-MC', 'fr-FR', 'en-US') # French (Monaco) + + # Spanish variants + 'es-ES' = @('es-ES', 'en-US') # Spanish (Spain) + 'es-MX' = @('es-MX', 'es-ES', 'en-US') # Spanish (Mexico) + 'es-AR' = @('es-AR', 'es-ES', 'en-US') # Spanish (Argentina) + 'es-CL' = @('es-CL', 'es-ES', 'en-US') # Spanish (Chile) + 'es-CO' = @('es-CO', 'es-ES', 'en-US') # Spanish (Colombia) + 'es-PE' = @('es-PE', 'es-ES', 'en-US') # Spanish (Peru) + 'es-VE' = @('es-VE', 'es-ES', 'en-US') # Spanish (Venezuela) + 'es-UY' = @('es-UY', 'es-AR', 'es-ES', 'en-US') # Spanish (Uruguay) + 'es-PY' = @('es-PY', 'es-AR', 'es-ES', 'en-US') # Spanish (Paraguay) + 'es-BO' = @('es-BO', 'es-ES', 'en-US') # Spanish (Bolivia) + 'es-EC' = @('es-EC', 'es-ES', 'en-US') # Spanish (Ecuador) + 'es-US' = @('es-US', 'es-MX', 'es-ES', 'en-US') # Spanish (United States) + + # German variants + 'de-DE' = @('de-DE', 'en-US') # German (Germany) + 'de-AT' = @('de-AT', 'de-DE', 'en-US') # German (Austria) + 'de-CH' = @('de-CH', 'de-DE', 'en-US') # German (Switzerland) + 'de-LI' = @('de-LI', 'de-CH', 'de-DE', 'en-US') # German (Liechtenstein) + 'de-LU' = @('de-LU', 'de-DE', 'en-US') # German (Luxembourg) + + # Italian variants + 'it-IT' = @('it-IT', 'en-US') # Italian (Italy) + 'it-CH' = @('it-CH', 'it-IT', 'en-US') # Italian (Switzerland) + 'it-SM' = @('it-SM', 'it-IT', 'en-US') # Italian (San Marino) + 'it-VA' = @('it-VA', 'it-IT', 'en-US') # Italian (Vatican) + + # Japanese variants + 'ja-JP' = @('ja-JP', 'en-US') # Japanese (Japan) + + # Portuguese variants + 'pt-PT' = @('pt-PT', 'en-US') # Portuguese (Portugal) + 'pt-BR' = @('pt-BR', 'pt-PT', 'en-US') # Portuguese (Brazil) + 'pt-AO' = @('pt-AO', 'pt-PT', 'en-US') # Portuguese (Angola) + 'pt-MZ' = @('pt-MZ', 'pt-PT', 'en-US') # Portuguese (Mozambique) + + # Russian variants + 'ru-RU' = @('ru-RU', 'en-US') # Russian (Russia) + 'ru-BY' = @('ru-BY', 'ru-RU', 'en-US') # Russian (Belarus) + 'ru-KZ' = @('ru-KZ', 'ru-RU', 'en-US') # Russian (Kazakhstan) + + # Arabic variants + 'ar-SA' = @('ar-SA', 'en-US') # Arabic (Saudi Arabia) + 'ar-EG' = @('ar-EG', 'ar-SA', 'en-US') # Arabic (Egypt) + 'ar-AE' = @('ar-AE', 'ar-SA', 'en-US') # Arabic (UAE) + 'ar-JO' = @('ar-JO', 'ar-SA', 'en-US') # Arabic (Jordan) + 'ar-LB' = @('ar-LB', 'ar-SA', 'en-US') # Arabic (Lebanon) + + # Korean variants + 'ko-KR' = @('ko-KR', 'en-US') # Korean (South Korea) + 'ko-KP' = @('ko-KP', 'ko-KR', 'en-US') # Korean (North Korea) + + # Dutch variants + 'nl-NL' = @('nl-NL', 'en-US') # Dutch (Netherlands) + 'nl-BE' = @('nl-BE', 'nl-NL', 'en-US') # Dutch (Belgium) + + # Swedish variants + 'sv-SE' = @('sv-SE', 'en-US') # Swedish (Sweden) + 'sv-FI' = @('sv-FI', 'sv-SE', 'en-US') # Swedish (Finland) + + # Norwegian variants + 'nb-NO' = @('nb-NO', 'en-US') # Norwegian Bokmål + 'nn-NO' = @('nn-NO', 'nb-NO', 'en-US') # Norwegian Nynorsk + 'no-NO' = @('no-NO', 'nb-NO', 'en-US') # Norwegian (legacy) + + # Danish variants + 'da-DK' = @('da-DK', 'en-US') # Danish (Denmark) + 'da-GL' = @('da-GL', 'da-DK', 'en-US') # Danish (Greenland) + + # Finnish variants + 'fi-FI' = @('fi-FI', 'en-US') # Finnish (Finland) + + # Polish variants + 'pl-PL' = @('pl-PL', 'en-US') # Polish (Poland) + + # Czech variants + 'cs-CZ' = @('cs-CZ', 'en-US') # Czech (Czech Republic) + + # Hungarian variants + 'hu-HU' = @('hu-HU', 'en-US') # Hungarian (Hungary) + + # Turkish variants + 'tr-TR' = @('tr-TR', 'en-US') # Turkish (Turkey) + 'tr-CY' = @('tr-CY', 'tr-TR', 'en-US') # Turkish (Cyprus) + + # Greek variants + 'el-GR' = @('el-GR', 'en-US') # Greek (Greece) + 'el-CY' = @('el-CY', 'el-GR', 'en-US') # Greek (Cyprus) + + # Hebrew variants + 'he-IL' = @('he-IL', 'en-US') # Hebrew (Israel) + + # Hindi variants + 'hi-IN' = @('hi-IN', 'en-US') # Hindi (India) + + # Thai variants + 'th-TH' = @('th-TH', 'en-US') # Thai (Thailand) + + # Vietnamese variants + 'vi-VN' = @('vi-VN', 'en-US') # Vietnamese (Vietnam) + } + + # Automatic fallback for language families not explicitly mapped + $LanguageCode = $CultureName.Split('-')[0] + $LanguageFallbacks = @{ + 'en' = @('en-GB', 'en-US') + 'zh' = @('zh-CN', 'zh-Hans', 'en-US') + 'fr' = @('fr-FR', 'en-US') + 'es' = @('es-ES', 'en-US') + 'de' = @('de-DE', 'en-US') + 'it' = @('it-IT', 'en-US') + 'ja' = @('ja-JP', 'en-US') + 'pt' = @('pt-PT', 'en-US') + 'ru' = @('ru-RU', 'en-US') + 'ar' = @('ar-SA', 'en-US') + 'ko' = @('ko-KR', 'en-US') + 'nl' = @('nl-NL', 'en-US') + 'sv' = @('sv-SE', 'en-US') + 'no' = @('nb-NO', 'en-US') + 'nb' = @('nb-NO', 'en-US') + 'nn' = @('nn-NO', 'nb-NO', 'en-US') + 'da' = @('da-DK', 'en-US') + 'fi' = @('fi-FI', 'en-US') + 'pl' = @('pl-PL', 'en-US') + 'cs' = @('cs-CZ', 'en-US') + 'hu' = @('hu-HU', 'en-US') + 'tr' = @('tr-TR', 'en-US') + 'el' = @('el-GR', 'en-US') + 'he' = @('he-IL', 'en-US') + 'hi' = @('hi-IN', 'en-US') + 'th' = @('th-TH', 'en-US') + 'vi' = @('vi-VN', 'en-US') + } + + # Return explicit mapping if exists + if ($CultureMappings.ContainsKey($CultureName)) { + return $CultureMappings[$CultureName] + } + + # Return language family fallback if exists + if ($LanguageFallbacks.ContainsKey($LanguageCode)) { + return @($CultureName) + $LanguageFallbacks[$LanguageCode] + } + + # Final fallback + return @($CultureName, 'en-US') +} \ No newline at end of file diff --git a/AsBuiltReport.Core/Src/Private/Write-ReportModuleInfo.ps1 b/AsBuiltReport.Core/Src/Private/Write-ReportModuleInfo.ps1 new file mode 100644 index 0000000..14df024 --- /dev/null +++ b/AsBuiltReport.Core/Src/Private/Write-ReportModuleInfo.ps1 @@ -0,0 +1,94 @@ +function Write-ReportModuleInfo { + <# + .SYNOPSIS + Displays informational messages about the report module being executed. + + .DESCRIPTION + This function displays standardized informational messages about the report module, + including documentation links and version information. The output method varies based + on whether verbose mode is enabled: + - Verbose mode: Uses Write-PScriboMessage for consistent logging + - Non-verbose mode: Uses Write-Host for user-friendly colored output + + .PARAMETER ModuleName + The name of the report module (e.g., 'Microsoft.Azure', 'VMware.vSphere'). + This is used to construct GitHub URLs and module-specific messages. + + .EXAMPLE + Write-ReportModuleInfo -ModuleName 'Microsoft.Azure' + + Displays informational messages about the Microsoft Azure report module. + + .EXAMPLE + Write-ReportModuleInfo -ModuleName 'VMware.vSphere' + + Displays informational messages about the VMware vSphere report module. + + .NOTES + This function uses the global $translate variable for localized messages. + The function automatically detects verbose mode using $VerbosePreference. + Requires [CmdletBinding()] on the calling function to properly inherit -Verbose parameter. + #> + + [CmdletBinding()] + param ( + [Parameter(Mandatory = $true)] + [ValidateNotNullOrEmpty()] + [String] $ModuleName + ) + + # Construct the full module name + $FullModuleName = "AsBuiltReport.$ModuleName" + + # Display informational messages - use appropriate output method based on verbose preference + if ($VerbosePreference -eq 'Continue') { + # Check the current report module version + $InstalledVersion = Get-Module -ListAvailable -Name $FullModuleName -ErrorAction SilentlyContinue | + Sort-Object -Property Version -Descending | + Select-Object -First 1 -ExpandProperty Version + + if ($InstalledVersion) { + Write-PScriboMessage -Plugin "Module" -Message ($translate.ReportModuleInstalled -f $FullModuleName, "v$($InstalledVersion.ToString())") + + $LatestVersion = Find-Module -Name $FullModuleName -Repository PSGallery -ErrorAction SilentlyContinue | + Select-Object -ExpandProperty Version + + if ($LatestVersion -and ($InstalledVersion -lt $LatestVersion)) { + Write-PScriboMessage -Plugin "Module" -IsWarning -Message ($translate.ReportModuleAvailable -f $FullModuleName, "v$($LatestVersion.ToString())") + Write-PScriboMessage -Plugin "Module" -IsWarning -Message ($translate.ReportModuleUpdate -f $FullModuleName) + } + } + + # Verbose mode - use Write-PScriboMessage for consistent logging + Write-PScriboMessage -Plugin "Module" -Message ($translate.ReportModuleInfo1 -f $ModuleName) + Write-PScriboMessage -Plugin "Module" -Message ($translate.ReportModuleInfo2 -f $ModuleName) + Write-PScriboMessage -Plugin "Module" -Message $translate.ReportModuleInfo3 + Write-PScriboMessage -Plugin "Module" -Message $translate.ProjectWebsite + Write-PScriboMessage -Plugin "Module" -Message $translate.CommunityProject + + } else { + # Check the current report module version + $InstalledVersion = Get-Module -ListAvailable -Name $FullModuleName -ErrorAction SilentlyContinue | + Sort-Object -Property Version -Descending | + Select-Object -First 1 -ExpandProperty Version + + if ($InstalledVersion) { + Write-Host -ForegroundColor White " - $(($translate.ReportModuleInstalled -f $FullModuleName, "v$($InstalledVersion.ToString())"))" + + $LatestVersion = Find-Module -Name $FullModuleName -Repository PSGallery -ErrorAction SilentlyContinue | + Select-Object -ExpandProperty Version + + if ($LatestVersion -and ($InstalledVersion -lt $LatestVersion)) { + Write-Host -ForegroundColor Red ($translate.ReportModuleAvailable -f $FullModuleName, "v$($LatestVersion.ToString())") + Write-Host -ForegroundColor Red ($translate.ReportModuleUpdate -f $FullModuleName) + } + } + + # Non-verbose mode - use Write-Host for user-friendly output + Write-Host -ForegroundColor White " - $(($translate.ReportModuleInfo1 -f $ModuleName))" + Write-Host -ForegroundColor White " - $(($translate.ReportModuleInfo2 -f $ModuleName))" + Write-Host -ForegroundColor White " - $($translate.ReportModuleInfo3)" + Write-Host -ForegroundColor White " - $($translate.ProjectWebsite)" + Write-Host -ForegroundColor White " - $($translate.CommunityProject)" + } +} diff --git a/AsBuiltReport.Core/Src/Public/New-AsBuiltConfig.ps1 b/AsBuiltReport.Core/Src/Public/New-AsBuiltConfig.ps1 new file mode 100644 index 0000000..4eb8e06 --- /dev/null +++ b/AsBuiltReport.Core/Src/Public/New-AsBuiltConfig.ps1 @@ -0,0 +1,447 @@ +function New-AsBuiltConfig { + <# + .SYNOPSIS + Creates As Built Report configuration files. + .DESCRIPTION + New-AsBuiltConfig starts a menu-driven procedure in the powershell console and asks the user a series of questions + Answers to these questions are optionally saved in a JSON configuration file which can then be referenced using the + -AsBuiltConfigFilePath parameter using New-AsBuiltReport, to save having to answer these questions again and also to allow + the automation of New-AsBuiltReport. + + New-AsBuiltConfig will automatically be called by New-AsBuiltReport if the -AsBuiltConfigFilePath parameter is not specified + If a user wants to generate a new As Built Report configuration without running a new report, this cmdlet is exported + in the AsBuiltReport powershell module and can be called as a standalone cmdlet. + .EXAMPLE + New-AsBuiltConfig + + Starts the interactive configuration wizard to create a new As Built Report configuration file. + You will be prompted for report author, company information, email settings, and save location. + .EXAMPLE + $Config = New-AsBuiltConfig + + Creates a new As Built Report configuration and stores it in the $Config variable. + The configuration can be used with New-AsBuiltReport without specifying -AsBuiltConfigFilePath. + .LINK + https://github.com/AsBuiltReport/AsBuiltReport.Core + .LINK + https://www.asbuiltreport.com/user-guide/new-asbuiltconfig/ + #> + + [CmdletBinding()] + param() + + begin { + #Run section to prompt user for information about the As Built Report to be exported to JSON format (if saved) + $global:Config = @{ } + Initialize-LocalizedData -ModuleType 'Core' -ModuleBasePath (Split-Path (Split-Path $PSScriptRoot -Parent) -Parent) -LanguageFile 'New-AsBuiltConfig' + + } + + process { + Clear-Host + #region Report configuration + # Show As Built Report configuration banner + Draw-AsciiBanner -Lines @($translate.ReportInfo.BannerTitle) -TextColor 'Cyan' -SeparatorColor 'Cyan' + + $ReportAuthor = Read-Host -Prompt ($translate.ReportInfo.ReportAuthor -f [System.Environment]::Username) + if (($null -eq $ReportAuthor) -or ($ReportAuthor -eq "")) { + $ReportAuthor = $([System.Environment]::Username) + } + + $Config.Report = @{ + 'Author' = $ReportAuthor + } + #endregion Report configuration + + #region Company configuration + Clear-Host + # Show Company configuration banner + Draw-AsciiBanner -Lines @($translate.CompanyConfig.BannerTitle) -TextColor 'Cyan' -SeparatorColor 'Cyan' + + $CompanyInfo = Read-Host -Prompt $translate.CompanyConfig.CompanyInfo + if (($null -eq $CompanyInfo) -or ($CompanyInfo -eq "")) { + $CompanyInfo = "n" + } + while ("y", "n" -notcontains $CompanyInfo) { + $CompanyInfo = Read-Host -Prompt $translate.CompanyConfig.CompanyInfo + if (($null -eq $CompanyInfo) -or ($CompanyInfo -eq "")) { + $CompanyInfo = "n" + } + } + + if ($CompanyInfo -eq 'y') { + $CompanyFullName = Read-Host -Prompt $translate.CompanyConfig.CompanyFullName + $CompanyShortName = Read-Host -Prompt $translate.CompanyConfig.CompanyShortName + $CompanyContact = Read-Host -Prompt $translate.CompanyConfig.CompanyContact + do { + $CompanyEmail = Read-Host -Prompt $translate.CompanyConfig.CompanyEmail + + if (($null -eq $CompanyEmail) -or ($CompanyEmail -eq "")) { + # Allow blank/empty - no validation needed + $isValid = $true + } else { + # Validate email format if text is entered + try { + $null = [System.Net.Mail.MailAddress]$CompanyEmail + $isValid = $true + } catch { + Write-Host ($translate.EmailConfig.InvalidEmail -f $CompanyEmail) -ForegroundColor Red + $isValid = $false + } + } + } while (-not $isValid) + $CompanyPhone = Read-Host -Prompt $translate.CompanyConfig.CompanyPhone + $CompanyAddress = Read-Host -Prompt $translate.CompanyConfig.CompanyAddress + } + + $Config.Company = @{ + 'FullName' = $CompanyFullName + 'ShortName' = $CompanyShortName + 'Contact' = $CompanyContact + 'Email' = $CompanyEmail + 'Phone' = $CompanyPhone + 'Address' = $CompanyAddress + } + #endregion Company configuration + + #region Email configuration + Clear-Host + # Show Email configuration banner + Draw-AsciiBanner -Lines @($translate.EmailConfig.BannerTitle) -TextColor 'Cyan' -SeparatorColor 'Cyan' + if (-not ($SendEmail)) { + $ConfigureMailSettings = Read-Host -Prompt $translate.EmailConfig.ConfigureMailSettings + if (($null -eq $ConfigureMailSettings) -or ($ConfigureMailSettings -eq "")) { + $ConfigureMailSettings = "n" + } + while ("y", "n" -notcontains $ConfigureMailSettings) { + $ConfigureMailSettings = Read-Host -Prompt $translate.EmailConfig.ConfigureMailSettings + if (($null -eq $ConfigureMailSettings) -or ($ConfigureMailSettings -eq "")) { + $ConfigureMailSettings = "n" + } + } + } + if (($SendEmail) -or ($ConfigureMailSettings -eq "y")) { + do { + $MailServer = Read-Host -Prompt $translate.EmailConfig.MailServer + + if (($null -eq $MailServer) -or ($MailServer -eq "")) { + Write-Host $translate.EmailConfig.EmptyMailServerAddress -ForegroundColor Red + $isValid = $false + } else { + # Check if it's a valid IPv4 address (strict validation) + $ipParts = $MailServer.Split('.') + $isValidIPv4 = $false + + if ($ipParts.Count -eq 4) { + $isValidIPv4 = $true + foreach ($part in $ipParts) { + $num = 0 + if (-not [int]::TryParse($part, [ref]$num) -or $num -lt 0 -or $num -gt 255) { + $isValidIPv4 = $false + break + } + } + } + + # Check if it's a valid IPv6 address + $isValidIPv6 = $false + if (-not $isValidIPv4) { + try { + $parsedIP = [System.Net.IPAddress]::Parse($MailServer) + $isValidIPv6 = $parsedIP.AddressFamily -eq 'InterNetworkV6' + } catch { + $isValidIPv6 = $false + } + } + + # Check if it's a valid FQDN - but exclude things that look like incomplete IPs + $isValidFQDN = $false + if (-not $isValidIPv4 -and -not $isValidIPv6) { + # Exclude strings that are all numeric with dots (incomplete IPs) + $looksLikeIP = $MailServer -match '^[\d\.]+$' + + if (-not $looksLikeIP) { + $fqdnPattern = '^[a-zA-Z0-9]([a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])?(\.[a-zA-Z0-9]([a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])?)+$' + $isValidFQDN = $MailServer -match $fqdnPattern + } + } + + if ($isValidIPv4 -or $isValidIPv6 -or $isValidFQDN) { + $isValid = $true + } else { + Write-Host ($translate.EmailConfig.InvalidMailServer -f $MailServer) -ForegroundColor Red + $isValid = $false + } + } + } while (-not $isValid) + + if (($MailServer -eq 'smtp.office365.com') -or ($MailServer -eq 'smtp.gmail.com')) { + do { + $MailServerPort = Read-Host -Prompt $translate.EmailConfig.MailServerPort587 + $portNumber = 0 # Initialize the variable + + if (($null -eq $MailServerPort) -or ($MailServerPort -eq "")) { + $MailServerPort = '587' + $isValid = $true + } elseif ([int]::TryParse($MailServerPort, [ref]$portNumber) -and $portNumber -ge 1 -and $portNumber -le 65535) { + $isValid = $true + } else { + Write-Host $translate.EmailConfig.InvalidMailServerPort587 -ForegroundColor Red + $isValid = $false + } + } while (-not $isValid) + } else { + do { + $MailServerPort = Read-Host -Prompt $translate.EmailConfig.MailServerPort25 + $portNumber = 0 # Initialize the variable + + if (($null -eq $MailServerPort) -or ($MailServerPort -eq "")) { + $MailServerPort = '25' + $isValid = $true + } elseif ([int]::TryParse($MailServerPort, [ref]$portNumber) -and $portNumber -ge 1 -and $portNumber -le 65535) { + $isValid = $true + } else { + Write-Host $translate.EmailConfig.InvalidMailServerPort25 -ForegroundColor Red + $isValid = $false + } + } while (-not $isValid) + } + + $MailServerUseSSL = Read-Host -Prompt $translate.EmailConfig.MailServerUseSSL + if (($null -eq $MailServerUseSSL) -or ($MailServerUseSSL -eq "")) { + $MailServerUseSSL = "n" + } + while ("y", "n" -notcontains $MailServerUseSSL) { + $MailServerUseSSL = Read-Host -Prompt $translate.EmailConfig.MailServerUseSSL + if (($null -eq $MailServerUseSSL) -or ($MailServerUseSSL -eq "")) { + $MailServerUseSSL = "n" + } + } + $MailServerUseSSL = switch ($MailServerUseSSL) { + "y" { $true } + "n" { $false } + } + + $MailCredentials = Read-Host -Prompt $translate.EmailConfig.MailCredentials + if (($null -eq $MailCredentials) -or ($MailCredentials -eq "")) { + $MailCredentials = "n" + } + while ("y", "n" -notcontains $MailCredentials) { + $MailCredentials = Read-Host -Prompt $translate.EmailConfig.MailCredentials + if (($null -eq $MailCredentials) -or ($MailCredentials -eq "")) { + $MailCredentials = "n" + } + } + $MailCredentials = switch ($MailCredentials) { + "y" { $true } + "n" { $false } + } + + do { + $MailFrom = Read-Host -Prompt $translate.EmailConfig.MailFrom + if (($null -eq $MailFrom) -or ($MailFrom -eq "")) { + Write-Host $translate.EmailConfig.EmptyEmail -ForegroundColor Red + $isValid = $false + } else { + try { + $null = [System.Net.Mail.MailAddress]$MailFrom + $isValid = $true + } catch { + $isValid = $false + Write-Host ($translate.EmailConfig.InvalidEmail -f $MailFrom) -ForegroundColor Red + } + } + } while (-not $isValid) + + $MailRecipients = @() + do { + do { + $MailTo = Read-Host -Prompt $translate.EmailConfig.MailTo + + if (($null -eq $MailTo) -or ($MailTo -eq "")) { + Write-Host $translate.EmailConfig.EmptyEmail -ForegroundColor Red + $isValid = $false + } else { + try { + $null = [System.Net.Mail.MailAddress]$MailTo + $isValidEmail = $true + } catch { + $isValidEmail = $false + Write-Host ($translate.EmailConfig.InvalidEmail -f $MailTo) -ForegroundColor Red + } + } + } while (-not $isValidEmail) + + $MailRecipients += $MailTo + $AnotherRecipient = @() + $AnotherRecipient = Read-Host -Prompt $translate.EmailConfig.AnotherRecipient + if (($null -eq $AnotherRecipient) -or ($AnotherRecipient -eq "")) { + $AnotherRecipient = "n" + } + while ("y", "n" -notcontains $AnotherRecipient) { + $AnotherRecipient = Read-Host -Prompt $translate.EmailConfig.AnotherRecipient + if (($null -eq $AnotherRecipient) -or ($AnotherRecipient -eq "")) { + $AnotherRecipient = "n" + } + } + } until($AnotherRecipient -eq "n") + $MailBody = Read-Host -Prompt $translate.EmailConfig.MailBodyPrompt + if (($null -eq $MailBody) -or ($MailBody -eq "")) { + $MailBody = $translate.EmailConfig.MailBody + } + } + + $Config.Email = @{ + 'Server' = $MailServer + 'Port' = $MailServerPort + 'UseSSL' = $MailServerUseSSL + 'Credentials' = $MailCredentials + 'From' = $MailFrom + 'To' = $MailRecipients + 'Body' = $MailBody + } + #endregion Email Configuration + + #region Report Configuration Folder + if ($Report -and (-not $ReportConfigFilePath)) { + Clear-Host + # Show Report configuration banner + Draw-AsciiBanner -Lines @($translate.ReportConfig.BannerTitle) -TextColor 'Cyan' -SeparatorColor 'Cyan' + $DefaultConfigFolder = Join-Path -Path $Home -ChildPath "AsBuiltReport" + $ReportConfigFolder = Read-Host -Prompt ($translate.ReportConfig.ReportConfigFolder -f $DefaultConfigFolder) + if (($null -eq $ReportConfigFolder) -or ($ReportConfigFolder -eq "")) { + $ReportConfigFolder = $DefaultConfigFolder + } + + #If the folder doesn't exist, create it + if (-not (Test-Path -Path $ReportConfigFolder)) { + try { + $Folder = New-Item -Path $ReportConfigFolder -ItemType Directory -Force + } catch { + Write-Error $_ + break + } + } + + # Add the path to the folder to the report configuration file + $Config.UserFolder = @{ + 'Path' = $ReportConfigFolder + } + + # Test to see if the report configuration file exists. If it doesn't exist, generate the report configuration file. + # If the report configuration file exists, prompt the user to overwrite the report configuration file. + $ReportModule = Get-Module -Name "AsBuiltReport.$Report" -ListAvailable | Sort-Object -Property Version -Descending | Select-Object -First 1 + $ReportModuleName = $ReportModule.Name + $SourcePath = Join-Path -Path $($ReportModule.ModuleBase) -ChildPath "$ReportModuleName.json" + $DestinationPath = Join-Path -Path $($ReportConfigFolder) -ChildPath "$ReportModuleName.json" + if (-not (Get-ChildItem -Path $DestinationPath)) { + Write-Verbose ($translate.CopyFile -f $SourcePath, $DestinationPath) + New-AsBuiltReportConfig -Report $Report -FolderPath $ReportConfigFolder + # Restore core translations after New-AsBuiltReportConfig (which loads its own translations) + Initialize-LocalizedData -ModuleType 'Core' -ModuleBasePath (Split-Path (Split-Path $PSScriptRoot -Parent) -Parent) -LanguageFile 'New-AsBuiltConfig' + } else { + try { + if (Test-Path -Path $DestinationPath) { + $OverwriteReportConfig = Read-Host -Prompt ($translate.ReportConfig.OverwriteReportConfig -f $ReportModuleName) + if (($null -eq $OverwriteReportConfig) -or ($OverwriteReportConfig -eq "")) { + $OverwriteReportConfig = "n" + } + while ("y", "n" -notcontains $OverwriteReportConfig) { + $OverwriteReportConfig = Read-Host -Prompt ($translate.ReportConfig.OverwriteReportConfig -f $ReportModuleName) + if (($null -eq $OverwriteReportConfig) -or ($OverwriteReportConfig -eq "")) { + $OverwriteReportConfig = "n" + } + } + if ($OverwriteReportConfig -eq 'y') { + try { + Write-Verbose ($translate.ReportConfig.OverwriteFile -f $SourcePath, $DestinationPath) + New-AsBuiltReportConfig -Report $Report -FolderPath $ReportConfigFolder -Force + # Restore core translations after New-AsBuiltReportConfig (which loads its own translations) + Initialize-LocalizedData -ModuleType 'Core' -ModuleBasePath (Split-Path (Split-Path $PSScriptRoot -Parent) -Parent) -LanguageFile 'New-AsBuiltConfig' + } catch { + Write-Error $_ + break + } + } + } + } catch { + Write-Error $_ + } + } + } + #endregion Report Configuration Folder + + #region Save configuration + Clear-Host + Draw-AsciiBanner -Lines @($translate.ReportConfig.BannerTitle) -TextColor 'Cyan' -SeparatorColor 'Cyan' + $SaveAsBuiltConfig = Read-Host -Prompt $translate.ReportConfig.SaveAsBuiltConfig + if (($null -eq $SaveAsBuiltConfig) -or ($SaveAsBuiltConfig -eq "")) { + $SaveAsBuiltConfig = "y" + } + while ("y", "n" -notcontains $SaveAsBuiltConfig) { + $SaveAsBuiltConfig = Read-Host -Prompt $translate.ReportConfig.SaveAsBuiltConfig + if (($null -eq $SaveAsBuiltConfig) -or ($SaveAsBuiltConfig -eq "")) { + $SaveAsBuiltConfig = "y" + } + } + + if ($SaveAsBuiltConfig -eq 'y') { + $AsBuiltName = Read-Host -Prompt $translate.ReportConfig.AsBuiltName + if (($null -eq $AsBuiltName) -or ($AsBuiltName -eq "")) { + $AsBuiltName = "AsBuiltReport" + } + if ($Config.UserFolder.Path) { + $AsBuiltExportPath = Read-Host -Prompt ($translate.ReportConfig.AsBuiltExportPath -f $Config.UserFolder.Path) + if (($null -eq $AsBuiltExportPath) -or ($AsBuiltExportPath -eq "")) { + $AsBuiltExportPath = $Config.UserFolder.Path + } + } elseif ($ReportConfigFilePath) { + $ReportConfigFolderPath = Split-Path -Path $ReportConfigFilePath + $AsBuiltExportPath = Read-Host -Prompt ($translate.ReportConfig.AsBuiltExportPath -f $ReportConfigFolderPath) + if (($null -eq $AsBuiltExportPath) -or ($AsBuiltExportPath -eq "")) { + $AsBuiltExportPath = $ReportConfigFolderPath + } + } else { + $DefaultConfigFolder = Join-Path -Path $Home -ChildPath "AsBuiltReport" + $AsBuiltExportPath = Read-Host -Prompt ($translate.ReportConfig.AsBuiltExportPath -f $DefaultConfigFolder) + if (($null -eq $AsBuiltExportPath) -or ($AsBuiltExportPath -eq "")) { + $AsBuiltExportPath = $DefaultConfigFolder + } + } + if (-not (Test-Path -Path $AsBuiltExportPath)) { + Write-Verbose ($translate.ReportConfig.ConfigFolder -f $AsBuiltExportPath) + try { + $Folder = New-Item -Path $AsBuiltExportPath -ItemType Directory -Force + } catch { + Write-Error $_ + break + } + } + $Config.UserFolder = @{ + 'Path' = $AsBuiltExportPath + } + Write-Verbose ($translate.ReportConfig.SaveConfig -f $AsBuiltName, $AsBuiltExportPath) + $AsBuiltConfigPath = Join-Path -Path $AsBuiltExportPath -ChildPath "$AsBuiltName.json" + $Config | ConvertTo-Json | Out-File $AsBuiltConfigPath + } else { + Write-Verbose $translate.ReportConfig.NotSaved + } + #endregion Save configuration + + # Print output to screen so that it can be captured to $Global:AsBuiltConfig variable in New-AsBuiltReport + $Config + + # Verbose Output + Write-Verbose "Config.Report.Author = $ReportAuthor" + Write-Verbose "Config.UserFolder.Path = $ReportConfigFolder" + foreach ($x in $Config.Company.Keys) { + Write-Verbose "Config.Company.$x = $($Config.Company[$x])" + } + foreach ($x in $Config.Email.Keys) { + Write-Verbose "Config.Email.$x = $($Config.Email[$x])" + } + Clear-Host + } + + end {} +}#End New-AsBuiltConfig Function \ No newline at end of file diff --git a/AsBuiltReport.Core/Src/Public/New-AsBuiltReport.ps1 b/AsBuiltReport.Core/Src/Public/New-AsBuiltReport.ps1 new file mode 100644 index 0000000..9742226 --- /dev/null +++ b/AsBuiltReport.Core/Src/Public/New-AsBuiltReport.ps1 @@ -0,0 +1,726 @@ +function New-AsBuiltReport { + <# + .SYNOPSIS + Documents the configuration of IT infrastructure in Word/HTML/Text formats using PScribo. + .DESCRIPTION + Documents the configuration of IT infrastructure in Word/HTML/Text formats using PScribo. + .PARAMETER Report + Specifies the type of report that will be generated. + .PARAMETER Target + Specifies the IP/FQDN of the system to connect. + Multiple targets may be specified, separated by a comma. + .PARAMETER Credential + Specifies the stored credential of the target system. + .PARAMETER Username + Specifies the username for the target system. + .PARAMETER Password + Specifies the password for the target system. + .PARAMETER Token + Specifies an API token to authenticate to the target system. + .PARAMETER UseInteractiveAuth + Use interactive authentication (via 3rd party identity provider) to authenticate to the target system. + This parameter has an alias 'MFA' for backwards compatibility. + .PARAMETER Format + Specifies the output format of the report. + The supported output formats are WORD, HTML & TEXT. + Multiple output formats may be specified, separated by a comma. + .PARAMETER ReportLanguage + Specifies the language for report content generated by the report module. + Available languages are dynamically determined based on language folders in the selected report module. + By default, the language will be set to en-US. + .PARAMETER Orientation + Sets the page orientation of the report to Portrait or Landscape. + By default, page orientation will be set to Portrait. + .PARAMETER StyleFilePath + Specifies the file path to a custom style .ps1 script for the report to use. + .PARAMETER OutputFolderPath + Specifies the folder path to save the report. + .PARAMETER Filename + Specifies a filename for the report. + .PARAMETER Timestamp + Specifies whether to append a timestamp string to the report filename. + By default, the timestamp string is not added to the report filename. + .PARAMETER EnableHealthCheck + Performs a health check of the target environment and highlights known issues within the report. + Not all reports may provide this functionality. + .PARAMETER SendEmail + Sends report to specified recipients as email attachments. + .PARAMETER AsBuiltConfigFilePath + Enter the full file path to the As Built Report configuration JSON file. + If this parameter is not specified, the user will be prompted for this configuration information on first + run, with the option to save the configuration to a file. + .PARAMETER ReportConfigFilePath + Enter the full file path to a report JSON configuration file + If this parameter is not specified, a default report configuration JSON is copied to the specifed user folder. + If this parameter is specified and the path to a JSON file is invalid, the script will terminate. + .EXAMPLE + New-AsBuiltReport -Report VMware.vSphere -Target 192.168.1.100 -Username admin -Password admin -Format HTML,Word -EnableHealthCheck -OutputFolderPath 'C:\Reports' + + Creates a VMware vSphere As Built Report in HTML & Word formats. The document will highlight particular issues which exist within the environment. + The report will be saved to C:\Reports. + .EXAMPLE + $Creds = Get-Credential + New-AsBuiltReport -Report PureStorage.FlashArray -Target 192.168.1.100 -Credential $Creds -Format Text -Timestamp -OutputFolderPath 'C:\Reports' + + Creates a Pure Storage FlashArray As Built Report in Text format and appends a timestamp to the filename. + Stored credentials are used to connect to the system. + The report will be saved to C:\Reports. + .EXAMPLE + New-AsBuiltReport -Report Veeam.VBR -Target veeam01.corp.local -Username admin -Password admin -Format HTML -Filename 'Veeam-Backup-Report' -OutputFolderPath 'C:\Reports' + + Creates a Veeam Backup & Replication As Built Report in HTML format with a custom filename. + The report will be saved as 'Veeam-Backup-Report.html' in C:\Reports. + .EXAMPLE + New-AsBuiltReport -Report Rubrik.CDM -Target 192.168.1.100 -Token 'eyJ0eXAiOiJKV1QiLCJhbGc...' -Format HTML -OutputFolderPath 'C:\Reports' + + Creates a Rubrik CDM As Built Report in HTML format. + An API token is used to connect to the system. + The report will be saved to C:\Reports. + .EXAMPLE + New-AsBuiltReport -Report Microsoft.Azure -Target 'tenant.onmicrosoft.com' -UseInteractiveAuth -Format Word -OutputFolderPath 'C:\Reports' + + Creates a Microsoft Azure As Built Report in Word format. + Interactive authentication (via web browser) is used to authenticate to Azure. + The report will be saved to C:\Reports. + .EXAMPLE + New-AsBuiltReport -Report NetApp.ONTAP -Target ontap.corp.local -Username admin -Password admin -Format HTML -Orientation Landscape -OutputFolderPath 'C:\Reports' + + Creates a NetApp ONTAP As Built Report in HTML format with Landscape page orientation. + The report will be saved to C:\Reports. + .EXAMPLE + New-AsBuiltReport -Report VMware.vSphere -Target vcenter.corp.local -Username admin -Password admin -Format Word -StyleFilePath 'C:\Styles\Corporate-Style.ps1' -OutputFolderPath 'C:\Reports' + + Creates a VMware vSphere As Built Report in Word format using a custom corporate style. + The report will be saved to C:\Reports. + .EXAMPLE + New-AsBuiltReport -Report Nutanix.PrismElement -Target 192.168.1.100 -Username admin -Password admin -Format Word -SendEmail -OutputFolderPath 'C:\Reports' + + Creates a Nutanix Prism Element As Built Report in Word format. Report will be attached and sent via email. + Email settings must be configured using New-AsBuiltConfig or -AsBuiltConfigFilePath parameter. + The report will be saved to C:\Reports. + .EXAMPLE + New-AsBuiltReport -Report VMware.vSphere -Target vcenter01.corp.local,vcenter02.corp.local -Username admin -Password admin -Format HTML -OutputFolderPath 'C:\Reports' + + Creates VMware vSphere As Built Reports in HTML format for multiple vCenter servers. + Separate reports will be generated for each target. + The reports will be saved to C:\Reports. + .EXAMPLE + New-AsBuiltReport -Report Microsoft.AD -Target dc01.corp.local -Username 'CORP\admin' -Password admin -Format HTML -ReportLanguage 'es-ES' -OutputFolderPath 'C:\Reports' + + Creates a Microsoft Active Directory As Built Report in HTML format with Spanish language content. + The report will be saved to C:\Reports. + .EXAMPLE + New-AsBuiltReport -Report DellEMC.VxRail -Target vxrail-mgr.corp.local -Username admin -Password admin -Format Word -AsBuiltConfigFilePath 'C:\Config\asbuiltreport.json' -OutputFolderPath 'C:\Reports' + + Creates a Dell EMC VxRail As Built Report in Word format, using the configuration in the asbuiltreport.json file. + The report will be saved to C:\Reports. + .EXAMPLE + New-AsBuiltReport -Report VMware.Horizon -Target horizon-cs.corp.local -Username admin -Password admin -Format HTML -ReportConfigFilePath 'C:\Config\VMware.Horizon.json' -OutputFolderPath 'C:\Reports' + + Creates a VMware Horizon As Built Report in HTML format, using a custom report configuration file. + The custom configuration allows you to control report depth and detail levels. + The report will be saved to C:\Reports. + .EXAMPLE + New-AsBuiltReport -Report Aruba.ClearPass -Target aruba.corp.local -Username admin -Password admin -Format HTML,Word,Text -Timestamp -EnableHealthCheck -OutputFolderPath 'C:\Reports' + + Creates an Aruba ClearPass As Built Report in HTML, Word, and Text formats with timestamp appended to the filename. + Health checks are enabled to highlight any configuration issues. + The reports will be saved to C:\Reports. + .LINK + https://github.com/AsBuiltReport/AsBuiltReport.Core + .LINK + https://www.asbuiltreport.com/user-guide/new-asbuiltreport/ + #> + + #region Script Parameters + [CmdletBinding( + PositionalBinding = $false, + DefaultParameterSetName = 'Credential' + )] + param ( + [Parameter( + Position = 0, + Mandatory = $true, + HelpMessage = 'Please specify which report type you wish to run.' + )] + [ValidateScript( { + $InstalledReportModules = Get-Module -Name "AsBuiltReport.*" -ListAvailable | Where-Object { $_.name -ne 'AsBuiltReport.Core' } | Sort-Object -Property Version -Descending | Select-Object -Unique + $ValidReports = foreach ($InstalledReportModule in $InstalledReportModules) { + $NameArray = $InstalledReportModule.Name.Split('.') + "$($NameArray[-2]).$($NameArray[-1])" + } + if ($ValidReports -contains $_) { + $true + } else { + throw "Invalid report type specified. Please use one of the following [$($ValidReports -Join ', ')]" + } + })] + [String] $Report, + + [Parameter( + Position = 1, + Mandatory = $true, + HelpMessage = 'Please provide the IP/FQDN of the system' + )] + [ValidateNotNullOrEmpty()] + [Alias('Cluster', 'Server', 'IP')] + [String[]] $Target, + [Parameter( + Position = 2, + Mandatory = $true, + HelpMessage = 'Please provide credentials to connect to the system', + ParameterSetName = 'Credential' + )] + [ValidateNotNullOrEmpty()] + [PSCredential] $Credential, + + [Parameter( + Position = 2, + Mandatory = $true, + HelpMessage = 'Please provide the username to connect to the target system', + ParameterSetName = 'UsernameAndPassword' + )] + [ValidateNotNullOrEmpty()] + [String] $Username, + + [Parameter( + Position = 3, + Mandatory = $false, + HelpMessage = 'Please provide the password to connect to the target system', + ParameterSetName = 'UsernameAndPassword' + )] + [ValidateNotNullOrEmpty()] + [String] $Password, + + [Parameter( + Position = 3, + Mandatory = $true, + HelpMessage = 'Please provide an API token to connect to the target system', + ParameterSetName = 'APIToken' + )] + [ValidateNotNullOrEmpty()] + [String] $Token, + + [Parameter( + Position = 3, + Mandatory = $true, + ParameterSetName = 'InteractiveAuth' + )] + [ValidateNotNullOrEmpty()] + [Alias('MFA')] + [Switch] $UseInteractiveAuth, + + [Parameter( + Position = 4, + Mandatory = $false, + HelpMessage = 'Please provide the document output format' + )] + [ValidateNotNullOrEmpty()] + [ValidateSet('Word', 'HTML', 'Text')] + [Array] $Format = 'Word', + + [Parameter( + Mandatory = $false, + HelpMessage = 'Please specify the language for the report content. Available languages are determined by language folders in the selected report module (default is en-US)' + )] + [ValidateNotNullOrEmpty()] + [ValidateScript({ + if ($Report) { + $ReportModuleName = "AsBuiltReport.$Report" + $ReportModule = Get-Module -Name $ReportModuleName -ListAvailable | Sort-Object -Property Version -Descending | Select-Object -First 1 + if ($ReportModule) { + $LanguagePath = Join-Path -Path $ReportModule.ModuleBase -ChildPath 'Language' + $AvailableLanguages = @() + if (Test-Path $LanguagePath) { + $AvailableLanguages = Get-ChildItem -Path $LanguagePath -Directory | Select-Object -ExpandProperty Name + } + if ($AvailableLanguages.Count -eq 0) { + $AvailableLanguages = @('en-US') + } + if ($_ -in $AvailableLanguages) { + $true + } else { + throw "Report Language '$_' is not supported for module '$ReportModuleName'. Available report languages are: $($AvailableLanguages -join ', ')" + } + } else { + # If report module not found, default to en-US validation + if ($_ -eq 'en-US') { + $true + } else { + throw "Report module '$ReportModuleName' not found. Defaulting to 'en-US' language." + } + } + } else { + # If no Report specified yet, allow any language for now + $true + } + })] + [String] $ReportLanguage, + + [Parameter( + Mandatory = $false, + HelpMessage = 'Determines the document page orientation' + )] + [ValidateNotNullOrEmpty()] + [ValidateSet('Portrait', 'Landscape')] + [String] $Orientation = 'Portrait', + + [Parameter( + Mandatory = $true, + HelpMessage = 'Please provide the path to the document output file' + )] + [ValidateNotNullOrEmpty()] + [Alias('OutputPath')] + [String] $OutputFolderPath, + + [Parameter( + Mandatory = $false, + HelpMessage = 'Please provide the path to the custom style script' + )] + [ValidateNotNullOrEmpty()] + [Alias('StylePath')] + [String] $StyleFilePath, + + [Parameter( + Mandatory = $false, + HelpMessage = 'Provide the file path to an existing report JSON Configuration file' + )] + [ValidateNotNullOrEmpty()] + [Alias('ReportConfigPath')] + [String] $ReportConfigFilePath, + + [Parameter( + Mandatory = $false, + HelpMessage = 'Provide the file path to an existing As Built JSON Configuration file' + )] + [ValidateNotNullOrEmpty()] + [Alias('AsBuiltConfigPath')] + [String] $AsBuiltConfigFilePath, + + [Parameter( + Mandatory = $false, + HelpMessage = 'Specify the As Built Report filename' + )] + [ValidateNotNullOrEmpty()] + [String] $Filename, + + [Parameter( + Mandatory = $false, + HelpMessage = 'Specify whether to append a timestamp to the document filename' + )] + [Switch] $Timestamp = $false, + + [Parameter( + Mandatory = $false, + HelpMessage = 'Specify whether to highlight any configuration issues within the document' + )] + [Switch] $EnableHealthCheck = $false, + + [Parameter( + Mandatory = $false, + HelpMessage = 'Specify whether to send report via Email' + )] + [Switch] $SendEmail = $false + ) + #endregion Script Parameters + + # Initialize core module localization with user's OS language + Initialize-LocalizedData -ModuleBasePath (Split-Path (Split-Path $PSScriptRoot -Parent) -Parent) -LanguageFile 'New-AsBuiltReport' -ModuleType 'Core' + + try { + + if ($psISE) { + Write-Error ($translate.PwshISE) -ErrorAction Stop + } + + # If Username and Password parameters used, convert specified Password to secure string and store in $Credential + if ($Username) { + if (-not $Password) { + # If the Password parameter is not provided, prompt for it securely + $SecurePassword = Read-Host ($translate.password -f $Username) -AsSecureString + } else { + # If the Password parameter is provided, convert it to secure string + $SecurePassword = ConvertTo-SecureString $Password -AsPlainText -Force + } + $Credential = New-Object System.Management.Automation.PSCredential ($Username, $SecurePassword) + } + + if (-not (Test-Path $OutputFolderPath)) { + Write-Error ($translate.OutputFolderPath -f $OutputFolderPath) -ErrorAction Stop + } + #region Variable config + + # Import the AsBuiltReport JSON configuration file + # If no path was specified, or the specified file doesn't exist, call New-AsBuiltConfig to walk the user through the menu prompt to create a config JSON + if ($AsBuiltConfigFilePath) { + if (Test-Path -Path $AsBuiltConfigFilePath) { + $Global:AsBuiltConfig = Get-Content -Path $AsBuiltConfigFilePath | ConvertFrom-Json + # Verbose Output for As Built Report configuration + Write-PScriboMessage -Plugin "Module" -Message ($translate.LoadConfig -f $AsBuiltConfigFilePath) + } else { + Write-Error ($translate.NoConfigFound -f $AsBuiltConfigFilePath) -ErrorAction Stop + } + } else { + Write-PScriboMessage -Plugin "Document" -Message $translate.GeneratingReport + $Global:AsBuiltConfig = New-AsBuiltConfig + # Restore core translations after New-AsBuiltConfig (which loads its own translations) + Initialize-LocalizedData -ModuleBasePath (Split-Path (Split-Path $PSScriptRoot -Parent) -Parent) -LanguageFile 'New-AsBuiltReport' -ModuleType 'Core' + } + + # Set ReportConfigFilePath as Global scope for use in New-AsBuiltConfig + if ($ReportConfigFilePath) { + $Global:ReportConfigFilePath = $ReportConfigFilePath + } + + # Set $OutputFolderPath as Global scope + if ($OutputFolderPath) { + $Global:OutputFolderPath = $OutputFolderPath + } + + # If StyleFilePath was specified, ensure the file provided in the path exists, otherwise exit with error + if ($StyleFilePath) { + if (-not (Test-Path -Path $StyleFilePath)) { + Write-Error ($translate.StyleScriptNotFound -f $StyleFilePath) -ErrorAction Stop + } + } + + # Report Module Information + $Global:Report = $Report + $ReportModuleName = "AsBuiltReport.$Report" + $CoreModulePath = (Get-Module -Name 'AsBuiltReport.Core' -ListAvailable | Sort-Object -Property Version -Descending | Select-Object -First 1).ModuleBase + $ReportModulePath = (Get-Module -Name $ReportModuleName -ListAvailable | Sort-Object -Property Version -Descending | Select-Object -First 1).ModuleBase + + # Initialize report module localization + # First, temporarily store the core translation + $CoreTranslations = $global:translate + + if ($ReportConfigFilePath) { + # If ReportConfigFilePath was specified, ensure the file provided in the path exists, otherwise exit with error + if (-not (Test-Path -Path $ReportConfigFilePath)) { + Write-Error ($translate.ReportModuleNotFound -f $ReportModuleName, $ReportConfigFilePath) -ErrorAction Stop + } else { + # Import the Report Configuration in to a variable + Write-PScriboMessage -Plugin "Document" -Message ($translate.LoadingReportConfig -f $ReportModuleName, $ReportConfigFilePath) + $Global:ReportConfig = Get-Content -Path $ReportConfigFilePath | ConvertFrom-Json + } + } else { + # If a report config hasn't been provided, check for the existance of the default JSON in the paths the user specified in base config + $ReportConfigFilePath = Join-Path -Path $ReportModulePath -ChildPath "$($ReportModuleName).json" + if (Test-Path -Path $ReportConfigFilePath) { + Write-PScriboMessage -Plugin "Document" -Message ($translate.LoadingReportConfig -f $ReportModuleName, $ReportConfigFilePath) + $Global:ReportConfig = Get-Content -Path $ReportConfigFilePath | ConvertFrom-Json + } else { + Write-Error ($translate.ReportConfigNotFound -f $ReportModulePath) -ErrorAction Stop + } + } + + # Determine final report language (ReportLanguage parameter overrides JSON config) + $FinalReportLanguage = if ($PSBoundParameters.ContainsKey('ReportLanguage')) { + # Parameter was explicitly specified by user + $ReportLanguage + } elseif ($ReportConfig.Report.Language) { + # Use language from JSON config if available + $ReportConfig.Report.Language + } else { + # Fallback to default + 'en-US' + } + + # Initialize report module translations with the final determined language + if ($ReportModulePath) { + try { + # Try to find a report-specific language file (most report modules use the report name) + $ReportLanguageFile = ($Report -replace '\.', '') + Initialize-LocalizedData -ModuleBasePath $ReportModulePath -LanguageFile $ReportLanguageFile -ModuleType 'Report' -ModuleName $Report -Language $FinalReportLanguage + $ReportTranslations = $global:translate + } catch { + # If report-specific language file not found or invalid, determine severity + $ErrorMessage = $_.Exception.Message + if ($ErrorMessage -match "Error:") { + # This is a file validation error from Initialize-LocalizedData - this is FATAL + # The file exists but has syntax errors (duplicate keys, invalid PowerShell syntax, etc.) + Write-Error "Report module localization file error for $ReportModuleName`: $ErrorMessage`n`nPlease fix the language file syntax errors before running the report." -ErrorAction Stop + } else { + # This is a file not found error - warn but allow to continue with empty translations + Write-Warning "Report module localization not found for $ReportModuleName. Using default language '$FinalReportLanguage'." + $ReportTranslations = @{} + } + } + } else { + $ReportTranslations = @{} + } + + # Restore core translations and set report translations separately + $global:translate = $CoreTranslations + $global:reportTranslate = $ReportTranslations + + # If Filename parameter is not specified, set filename to the report name + if (-not $Filename) { + $FileName = $ReportConfig.Report.Name + } + # If Timestamp parameter is specified, add the timestamp to the report filename + if ($Timestamp) { + $FileName = $Filename + " - " + (Get-Date -Format 'yyyy-MM-dd_HH.mm.ss') + } + Write-PScriboMessage -Plugin "Document" -Message ($translate.SetReportFileName -f $FileName) + + # If the EnableHealthCheck parameter has been specified, set the global healthcheck variable so report scripts can reference the health checks + if ($EnableHealthCheck) { + $Global:Healthcheck = $ReportConfig.HealthCheck + } + + # Set Global scope for Orientation parameter + $Global:Orientation = $Orientation + + #endregion Variable config + + #region Email Server Authentication + # If Email Server Authentication is required, prompt user for credentials + if ($SendEmail -and $AsBuiltConfig.Email.Credentials) { + Clear-Host + Draw-AsciiBox -Lines @($translate.EmailBannerTitle) -ExtraPadding 4 -TextColor 'Cyan' -BorderColor 'Cyan' + $MailCredentials = Get-Credential -Message ($translate.EmailCredentials -f $AsBuiltConfig.Email.Server) + Clear-Host + } + #endregion Email Server Authentication + + # Check installed module version + Try { + $InstalledVersion = Get-Module -ListAvailable -Name AsBuiltReport.Core -ErrorAction SilentlyContinue | Sort-Object -Property Version -Descending | Select-Object -First 1 -ExpandProperty Version + + if ($InstalledVersion) { + Write-PScriboMessage -Plugin "Module" -Message ($translate.InstalledModule -f $($InstalledVersion.ToString())) + $LatestVersion = Find-Module -Name AsBuiltReport.Core -Repository PSGallery -ErrorAction SilentlyContinue | Select-Object -ExpandProperty Version + if ($LatestVersion -gt $InstalledVersion) { + Write-PScriboMessage -Plugin "Module" -Message ($translate.AvailableModule -f $($LatestVersion.ToString())) + Write-PScriboMessage -Plugin "Module" -Message $translate.UpdateModule + } + } + } Catch { + Write-PscriboMessage -Plugin "Module" -IsWarning $_.Exception.Message + } + + #region Generate PScribo document + # if Verbose has been passed + if ($PSCmdlet.MyInvocation.BoundParameters["Verbose"].IsPresent) { + $AsBuiltReport = Document $FileName -Verbose { + Write-PScriboMessage -Plugin "Document" -Message ($translate.ReportGenerating -f $($Report.Replace(".", " "))) + # Set Document Style + if ($StyleFilePath) { + Write-PScriboMessage -Plugin "Document" -Message ($translate.ReportStyleScript -f $StyleFilePath) + . $StyleFilePath + } else { + $StyleFilePath = Join-Path -Path $CoreModulePath -ChildPath 'AsBuiltReport.Core.Style.ps1' + Write-PScriboMessage -Plugin "Document" -Message ($translate.ReportStyleScript -f $StyleFilePath) + . $StyleFilePath + } + + # Restore core translations after style script (style script loads its own translations) + $global:translate = $CoreTranslations + + # If Credential has been passed or previously created via Username/Password + try { + if ($Credential) { + & "Invoke-$($ReportModuleName)" -Target $Target -Credential $Credential -Verbose -ErrorAction Stop + } + elseif ($Token) { + & "Invoke-$($ReportModuleName)" -Target $Target -Token $Token -Verbose -ErrorAction Stop + } + elseif ($UseInteractiveAuth) { + Write-PScriboMessage -Plugin "Module" -Message ($translate.InteractiveAuth) + & "Invoke-$($ReportModuleName)" -Target $Target -UseInteractiveAuth -Verbose -ErrorAction Stop + } + } catch { + Write-Error ($($translate.ExecutionFailed) -f $($_.Exception.Message)) -ErrorAction Stop + } + } + } else { + # Show progress messages for non-verbose report generation + Write-Host ($translate.ReportGenerating -f $($Report.Replace(".", " "))) -ForegroundColor Green + Write-Host ($translate.ReportInitializing) -ForegroundColor Cyan + + try { + $AsBuiltReport = Document $FileName { + Write-Host ($translate.DocumentStyle) -ForegroundColor Cyan + # Set Document Style + if ($StyleFilePath) { + #Write-Host ($translate.ReportStyleScript -f $StyleFilePath) + . $StyleFilePath + } else { + $StyleFilePath = Join-Path -Path $CoreModulePath -ChildPath 'AsBuiltReport.Core.Style.ps1' + #Write-Host ($translate.ReportStyleScript -f $StyleFilePath) + . $StyleFilePath + } + + # Restore core translations after style script (style script loads its own translations) + $global:translate = $CoreTranslations + + Write-Host ($translate.TargetSystem) -ForegroundColor Cyan + try { + # If Credential has been passed or previously created via Username/Password + if ($Credential) { + & "Invoke-$($ReportModuleName)" -Target $Target -Credential $Credential -ErrorAction Stop + } + elseif ($Token) { + & "Invoke-$($ReportModuleName)" -Target $Target -Token $Token -ErrorAction Stop + } + elseif ($UseInteractiveAuth) { + & "Invoke-$($ReportModuleName)" -Target $Target -UseInteractiveAuth -ErrorAction Stop + } + } catch { + Write-Error ($($translate.ExecutionFailed) -f $($_.Exception.Message)) -ErrorAction Stop + } + Write-Host ($translate.BuildingDocument) -ForegroundColor Cyan + } + Write-Host ($translate.ExportingDocument) -ForegroundColor Cyan + } catch { + Write-Host ($translate.Failed) -ForegroundColor Red + throw + } + } + Try { + $Document = $AsBuiltReport | Export-Document -Path $OutputFolderPath -Format $Format -Options @{ TextWidth = 240 } -PassThru + # Ensure core translations are available + if (-not $translate.OutputFolder) { + $CoreModuleBasePath = Split-Path (Split-Path $PSScriptRoot -Parent) -Parent + Initialize-LocalizedData -ModuleBasePath $CoreModuleBasePath -LanguageFile 'New-AsBuiltReport' -ModuleType 'Core' + } + Write-Host ($translate.OutputFolder -f $($Report.Replace(".", " ")), $FileName, $OutputFolderPath) -ForegroundColor Green + } catch { + $Err = $_ + Write-Error $Err + } + #endregion Generate PScribo document + + #region Send-Email + if ($SendEmail) { + $EmailArguments = @{ + Attachments = $Document + To = $AsBuiltConfig.Email.To + From = $AsBuiltConfig.Email.From + Subject = $ReportConfig.Report.Name + Body = $AsBuiltConfig.Email.Body + SmtpServer = $AsBuiltConfig.Email.Server + Port = $AsBuiltConfig.Email.Port + UseSSL = $AsBuiltConfig.Email.UseSSL + } + + if ($AsBuiltConfig.Email.Credentials) { + # Send the report via SMTP using SSL + Send-MailMessage @EmailArguments -Credential $MailCredentials + } else { + # Send the report via SMTP + Send-MailMessage @EmailArguments + } + } + #endregion Send-Email + + #region Globals cleanup + Remove-Variable -Name AsBuiltConfig -Scope Global + Remove-Variable -Name ReportConfig -Scope Global + Remove-Variable -Name Report -Scope Global + Remove-Variable -Name Orientation -Scope Global + if ($ReportConfigFilePath) { + Remove-Variable -Name ReportConfigFilePath + } + if ($Healthcheck) { + Remove-Variable -Name Healthcheck -Scope Global + } + if ($global:AsBuiltReportLocalizedWarnings) { + Remove-Variable -Name AsBuiltReportLocalizedWarnings -Scope Global + } + #endregion Globals cleanup + + } catch { + Write-Error $_ + } +} + +Register-ArgumentCompleter -CommandName 'New-AsBuiltReport' -ParameterName 'Report' -ScriptBlock { + param ( + $commandName, + $parameterName, + $wordToComplete, + $commandAst, + $fakeBoundParameter + ) + + $InstalledReportModules = Get-Module -Name "AsBuiltReport.*" -ListAvailable | Where-Object { $_.name -ne 'AsBuiltReport.Core' } | Sort-Object -Property Version -Descending | Select-Object -Unique + $ValidReports = foreach ($InstalledReportModule in $InstalledReportModules) { + $NameArray = $InstalledReportModule.Name.Split('.') + "$($NameArray[-2]).$($NameArray[-1])" + } + + $ValidReports | Where-Object { $_ -like "$wordToComplete*" } | ForEach-Object { + [System.Management.Automation.CompletionResult]::new($_, $_, 'ParameterValue', $_) + } +} + + +# Argument completer for ReportLanguage parameter - dynamically gets available languages from selected Report module +Register-ArgumentCompleter -CommandName 'New-AsBuiltReport' -ParameterName 'ReportLanguage' -ScriptBlock { + param ( + $commandName, + $parameterName, + $wordToComplete, + $commandAst, + $fakeBoundParameter + ) + + # Try to get the Report parameter value from the current command line + $ReportValue = $null + if ($fakeBoundParameter['Report']) { + $ReportValue = $fakeBoundParameter['Report'] + } else { + # Try to parse the Report value from the command AST + if ($commandAst) { + $reportParam = $commandAst.FindAll({ + $args[0] -is [System.Management.Automation.Language.CommandParameterAst] -and + $args[0].ParameterName -eq 'Report' + }, $true) | Select-Object -First 1 + + if ($reportParam) { + # Get the next element after -Report parameter + $paramIndex = $commandAst.CommandElements.IndexOf($reportParam) + if ($paramIndex -ge 0 -and ($paramIndex + 1) -lt $commandAst.CommandElements.Count) { + $nextElement = $commandAst.CommandElements[$paramIndex + 1] + if ($nextElement -is [System.Management.Automation.Language.StringConstantExpressionAst]) { + $ReportValue = $nextElement.Value + } + } + } + } + } + + # If we have a report module, get its available languages + if ($ReportValue) { + $ReportModuleName = "AsBuiltReport.$ReportValue" + $ReportModule = Get-Module -Name $ReportModuleName -ListAvailable | Sort-Object -Property Version -Descending | Select-Object -First 1 + if ($ReportModule) { + $LanguagePath = Join-Path -Path $ReportModule.ModuleBase -ChildPath 'Language' + $AvailableLanguages = @() + if (Test-Path $LanguagePath) { + $AvailableLanguages = Get-ChildItem -Path $LanguagePath -Directory | Select-Object -ExpandProperty Name + } + + if ($AvailableLanguages.Count -eq 0) { + $AvailableLanguages = @('en-US') + } + + $AvailableLanguages | Where-Object { $_ -like "$wordToComplete*" } | ForEach-Object { + [System.Management.Automation.CompletionResult]::new($_, $_, 'ParameterValue', $_) + } + } else { + # If report module not found, default to common languages + @('en-US') | Where-Object { $_ -like "$wordToComplete*" } | ForEach-Object { + [System.Management.Automation.CompletionResult]::new($_, $_, 'ParameterValue', $_) + } + } + } else { + # If no report specified, show common languages as fallback + @('en-US', 'es-ES', 'fr-FR', 'de-DE') | Where-Object { $_ -like "$wordToComplete*" } | ForEach-Object { + [System.Management.Automation.CompletionResult]::new($_, $_, 'ParameterValue', $_) + } + } +} + diff --git a/Src/Public/New-AsBuiltReportConfig.ps1 b/AsBuiltReport.Core/Src/Public/New-AsBuiltReportConfig.ps1 similarity index 70% rename from Src/Public/New-AsBuiltReportConfig.ps1 rename to AsBuiltReport.Core/Src/Public/New-AsBuiltReportConfig.ps1 index 7227c61..3c51655 100644 --- a/Src/Public/New-AsBuiltReportConfig.ps1 +++ b/AsBuiltReport.Core/Src/Public/New-AsBuiltReportConfig.ps1 @@ -72,48 +72,47 @@ function New-AsBuiltReportConfig { [Switch] $Force ) - $DirectorySeparatorChar = [System.IO.Path]::DirectorySeparatorChar + Initialize-LocalizedData -ModuleType 'Core' -ModuleBasePath (Split-Path (Split-Path $PSScriptRoot -Parent) -Parent) -LanguageFile 'New-AsBuiltReportConfig' # Test to ensure the path the user has specified does exist if (-not (Test-Path -Path $($FolderPath))) { - Write-Error "The folder '$($FolderPath)' does not exist. Please create the folder and run New-AsBuiltReportConfig again." - break + Write-Error ($translate.FolderNotExist -f $($FolderPath)) -ErrorAction Stop } # Find the root folder where the module is located for the report that has been specified try { $Module = Get-Module -Name "AsBuiltReport.$Report" -ListAvailable | Where-Object { $_.name -ne 'AsBuiltReport.Core' } | Sort-Object -Property Version -Descending | Select-Object -Unique - $SourcePath = $($Module.ModuleBase) + $($DirectorySeparatorChar) + $($Module.Name) + ".json" + $SourcePath = Join-Path -Path $($Module.ModuleBase) -ChildPath "$($Module.Name).json" if (Test-Path -Path $($SourcePath)) { - Write-Verbose -Message "Processing $($Module.Name) report configuration file from module $($Module), version $($Module.Version)." + Write-Verbose ($translate.ProcessConfig -f $Module.Name, $Module, $Module.Version) if ($Filename) { - $DestinationPath = $($FolderPath) + $($DirectorySeparatorChar) + $($Filename) + ".json" + $DestinationPath = Join-Path -Path $($FolderPath) -ChildPath "$($Filename).json" if (-not (Test-Path -Path $($DestinationPath))) { - Write-Verbose -Message "Copying report configuration file '$($SourcePath)' to '$($DestinationPath)'." + Write-Verbose ($translate.CopyConfig -f $SourcePath, $DestinationPath) Copy-Item -Path $($SourcePath) -Destination "$($DestinationPath)" - Write-Output "$($Module.Name) report configuration file '$($Filename).json' created in '$($FolderPath)'." + Write-Output ($translate.CreateConfig -f $Module.Name, $Filename, $FolderPath) } elseif ($Force) { - Write-Verbose -Message "Copying report configuration file '$($SourcePath)' to '$($DestinationPath)'. Overwriting existing file." + Write-Verbose ($translate.OverWriteConfig -f $SourcePath, $DestinationPath) Copy-Item -Path $($SourcePath) -Destination $($DestinationPath) -Force - Write-Output "$($Module.Name) report configuration file '$($Filename).json' created in '$($FolderPath)'." + Write-Output ($translate.CreateConfig -f $Module.Name, $Filename, $FolderPath) } else { - Write-Error "$($Module.Name) report configuration file '$($Filename).json' already exists in '$($FolderPath)'. Use 'Force' parameter to overwrite existing file." + Write-Error ($translate.ForceOverwrite -f $Module.Name, $Filename, $FolderPath) } } else { - $DestinationPath = $($FolderPath) + $($DirectorySeparatorChar) + $($Module.Name) + ".json" + $DestinationPath = Join-Path -Path $($FolderPath) -ChildPath "$($Module.Name).json" if (-not (Test-Path -Path $($DestinationPath))) { - Write-Verbose -Message "Copying $($Module.Name) report configuration file '$($SourcePath)' to '$($DestinationPath)'." + Write-Verbose ($translate.CopyModuleConfig -f $Module.Name, $SourcePath, $DestinationPath) Copy-Item -Path $($SourcePath) -Destination $($DestinationPath) - Write-Output "$($Module.Name) report configuration file '$($Module.Name).json' created in '$($FolderPath)'." + Write-Output ($translate.CreateConfig -f $Module.Name, $Module.Name, $FolderPath) } elseif ($Force) { - Write-Verbose -Message "Copying report configuration file '$($SourcePath)' to '$($DestinationPath)'. Overwriting existing file." + Write-Verbose ($translate.OverWriteConfig -f $SourcePath, $DestinationPath) Copy-Item -Path $($SourcePath) -Destination $($DestinationPath) -Force - Write-Output "$($Module.Name) report configuration file '$($Module.Name).json' created in '$($FolderPath)'." + Write-Output ($translate.CreateConfig -f $Module.Name, $Module.Name, $FolderPath) } else { - Write-Error "$($Module.Name) report configuration file '$($Module.Name).json' already exists in '$($FolderPath)'. Use 'Force' parameter to overwrite existing file." + Write-Error ($translate.ForceOverwrite -f $Module.Name, $Module.Name, $FolderPath) } } } else { - Write-Error "Report configuration file not found in module path '$($Module.ModuleBase)'." + Write-Error ($translate.ConfigNotFound -f $Module.ModuleBase) } } catch { Write-Error $_ diff --git a/CHANGELOG.md b/CHANGELOG.md index 77607c7..1035d53 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,45 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [1.5.0] - 2025-10-21 + +### Added +- Add multilingual support for AsBuiltReport Core module + - `Initialize-LocalizedData` function to handle localization for both Core and Report modules + - `Resolve-Culture` function with comprehensive culture fallback chains for 135+ culture variants + - Localized user prompts and messages in `New-AsBuiltConfig` function. Support for all main languages. + - `ReportLanguage` parameter added to `New-AsBuiltReport` function with dynamic validation based on available languages in individual report modules + - Support for setting default language in report JSON configuration files using the `Report.Language` property +- Add PowerShell module dependency checking for report modules with `Get-RequiredModule` function +- Add `Draw-AsciiBanner` function to improve user interface in `New-AsBuiltConfig` +- Add `Write-ReportModuleInfo` function to provide information on report modules +- Add `SECURITY.md` and `CODE_OF_CODUCT.md` documentation +- Add `Stale.yml` GitHub workflow to manage GitHub issues +- Add `FUNDING.yml` to provide sponsorship links +- Improve error handling with comprehensive try-catch blocks and meaningful error messages +- Improve error handling for localized data import +- Add Pester tests and GitHub workflow +- Add Dependabot configuration for automated dependency updates +- Add Codecov integration for code coverage reporting +- Add comprehensive unit tests for all Private functions + +### Changed +- Core module functions (`New-AsBuiltConfig`, `New-AsBuiltReport`, `New-AsBuiltReportConfig`) now default to user's OS language instead of hardcoded English +- Report modules default to 'en-US' when no other language is supported +- Update parameter validation to use ValidateScript blocks for dynamic language detection +- Update `AsBuiltReport.Core.Style.ps1` script to support language translation +- Enhanced error messages to include specific language and module information +- Improved progress messaging during report generation +- Update all y/n prompts in `New-AsBuiltConfig` to show defaults and handle empty input +- Renamed `MFA` parameter to `UseInteractiveAuth` (`MFA` alias retained for backwards compatibility) +- Update `README.md` and `CONTRIBUTING.md` documentation +- Update `LICENSE` +- Update GitHub Release action for new folder structures +- Update Stale workflow to mark issues stale after 60 days + +### Removed +- Remove sample style scripts + ## [1.4.3] - 2025-03-08 ### Changed @@ -125,7 +164,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [1.0.0] - 2019-03-26 ### Added -- `AsBuiltReport.Core` module created to provide core as built report functionality +- `AsBuiltReport.Core` module created to provide core AsBuiltReport functionality ### Changed - `AsBuiltReport` module simply becomes a manifest to install required core and report modules @@ -139,7 +178,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [0.4.0] - 2019-03-16 ### Added -- `New-AsbuiltConfig` cmdlet to generate a base As Built Report JSON configuration file +- `New-AsbuiltConfig` cmdlet to generate a base AsBuiltReport JSON configuration file - `New-AsBuiltReport` cmdlet to generate a report JSON configuration file - Username and Password parameters on `New-AsBuiltReport` - Support for setting the document orientation for the output report @@ -160,5 +199,5 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - New As-Built JSON configuration structure - new `AsBuiltConfigPath` parameter - allows unique configuration files to be created and saved - - if `AsBuiltConfigPath` parameter is not specified, user is prompted for As Built report configuration information + - if `AsBuiltConfigPath` parameter is not specified, user is prompted for AsBuiltReport configuration information - `New-AsBuiltConfig.ps1` & `Config.json` files are no longer required diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 0000000..542cf84 --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,146 @@ +# Code of Conduct + +The AsBuiltReport project is committed to fostering an open and welcoming environment for all contributors, users, and community members. + +## Our Pledge + +We as members, contributors, and leaders pledge to make participation in our +community a harassment-free experience for everyone, regardless of age, body +size, visible or invisible disability, ethnicity, sex characteristics, gender +identity and expression, level of experience, education, socio-economic status, +nationality, personal appearance, race, religion, or sexual identity +and orientation. + +We pledge to act and interact in ways that contribute to an open, welcoming, +diverse, inclusive, and healthy community. + +## Our Standards + +Examples of behavior that contributes to a positive environment for our +community include: + +* Demonstrating empathy and kindness toward other people +* Being respectful of differing opinions, viewpoints, and experiences +* Giving and gracefully accepting constructive feedback +* Accepting responsibility and apologizing to those affected by our mistakes, + and learning from the experience +* Focusing on what is best not just for us as individuals, but for the + overall community + +Examples of unacceptable behavior include: + +* The use of sexualized language or imagery, and sexual attention or + advances of any kind +* Trolling, insulting or derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or email + address, without their explicit permission +* Other conduct which could reasonably be considered inappropriate in a + professional setting + +## Technical Disagreements + +Technical disagreements are a normal part of open source development. When disagreements arise: + +* Focus on the technical merits of the solution +* Assume good intentions from all parties +* Seek to understand different perspectives +* Escalate to maintainers if consensus cannot be reached + +## Enforcement Responsibilities + +Community leaders are responsible for clarifying and enforcing our standards of +acceptable behavior and will take appropriate and fair corrective action in +response to any behavior that they deem inappropriate, threatening, offensive, +or harmful. + +Community leaders have the right and responsibility to remove, edit, or reject +comments, commits, code, wiki edits, issues, and other contributions that are +not aligned to this Code of Conduct, and will communicate reasons for moderation +decisions when appropriate. + +## Scope + +This Code of Conduct applies within all AsBuiltReport community spaces, including: + +* GitHub repositories (issues, pull requests, discussions) +* Official social media channels +* Community chat platforms +* Project events and meetups + +It also applies when an individual is officially representing the AsBuiltReport community in public spaces. +Examples of representing our community include using an official e-mail address, +posting via an official social media account, or acting as an appointed +representative at an online or offline event. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported to the community leaders responsible for enforcement at +support@asbuiltreport.com. + +All complaints will be reviewed and investigated promptly and fairly. + +All community leaders are obligated to respect the privacy and security of the +reporter of any incident. + +## Enforcement Guidelines + +Community leaders will follow these Community Impact Guidelines in determining +the consequences for any action they deem in violation of this Code of Conduct: + +### 1. Correction + +**Community Impact**: Use of inappropriate language or other behavior deemed +unprofessional or unwelcome in the community. + +**Consequence**: A private, written warning from community leaders, providing +clarity around the nature of the violation and an explanation of why the +behavior was inappropriate. A public apology may be requested. + +### 2. Warning + +**Community Impact**: A violation through a single incident or series +of actions. + +**Consequence**: A warning with consequences for continued behavior. No +interaction with the people involved, including unsolicited interaction with +those enforcing the Code of Conduct, for a specified period of time. This +includes avoiding interactions in community spaces as well as external channels +like social media. Violating these terms may lead to a temporary or +permanent ban. + +### 3. Temporary Ban + +**Community Impact**: A serious violation of community standards, including +sustained inappropriate behavior. + +**Consequence**: A temporary ban from any sort of interaction or public +communication with the community for a specified period of time. No public or +private interaction with the people involved, including unsolicited interaction +with those enforcing the Code of Conduct, is allowed during this period. +Violating these terms may lead to a permanent ban. + +### 4. Permanent Ban + +**Community Impact**: Demonstrating a pattern of violation of community +standards, including sustained inappropriate behavior, harassment of an +individual, or aggression toward or disparagement of classes of individuals. + +**Consequence**: A permanent ban from any sort of public interaction within +the community. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], +version 2.0, available at +https://www.contributor-covenant.org/version/2/0/code_of_conduct.html. + +Community Impact Guidelines were inspired by [Mozilla's code of conduct +enforcement ladder](https://github.com/mozilla/diversity). + +[homepage]: https://www.contributor-covenant.org + +For answers to common questions about this code of conduct, see the FAQ at +https://www.contributor-covenant.org/faq. Translations are available at +https://www.contributor-covenant.org/translations. \ No newline at end of file diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 051ce2a..f969a73 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,164 +1,200 @@ -# Contributing to AsBuiltReport -Your contribution is welcomed and appreciated. Contributing to this project is as easy as: +# Contributing to AsBuiltReport.Core -- Discussing the current state of the code -- Proposing new features -- Reporting an issue or bug -- Submitting a fix -- Creating a new report module +Your contribution is welcomed and appreciated! Thank you for taking the time to contribute to this project. + +Please take a moment to review this document to make the contribution process easy and effective for everyone involved. -### Intro to Git and GitHub -* Make sure you have a [GitHub account](https://github.com/signup/free). -* Learning Git: - * [Learning Git and GitHub](https://help.github.com/articles/good-resources-for-learning-git-and-github/) - * [Git Branching](https://learngitbranching.js.org/) +Following these guidelines helps to communicate that you respect the time of the developers managing and developing this open source project. In return, they should reciprocate that respect in addressing your issue or assessing patches and features. -### Develop with GitHub -This project uses GitHub to host code, to track issues and feature requests, as well as accept pull requests. +## Ways to Contribute -We use [GitHub Flow](https://docs.github.com/get-started/quickstart/github-flow) to collaborate and to propose changes to the codebase. We actively welcome your pull requests. +Contributing to this project is as easy as: -#### Forks and Pull Requests +- Reporting bugs and issues +- Proposing new features +- Discussing the current state of the code +- Submitting fixes and improvements +- Creating new report modules +- Improving documentation -GitHub fosters collaboration through the notion of [pull requests](https://help.github.com/articles/using-pull-requests/). On GitHub, anyone can [fork](https://help.github.com/articles/fork-a-repo/) an existing repository into their own user account, where they can make private changes to their fork. To contribute these changes back into the original repository, a user simply creates a pull request in order to "request" that the changes be taken "upstream". +For comprehensive contribution guidelines, please visit our [Developer Guide](https://www.asbuiltreport.com/dev-guide/contributing). -Additional references: +## Getting Started -- GitHub's guide on [Forking](https://docs.github.com/pull-requests/collaborating-with-pull-requests/working-with-forks/about-forks) -- GitHub's guide on [Contributing to Open Source](https://docs.github.com/get-started/exploring-projects-on-github/finding-ways-to-contribute-to-open-source-on-github) -- GitHub's guide on [Understanding the GitHub Flow](https://docs.github.com/get-started/quickstart/github-flow) +### Prerequisites -#### Version control branching +- A [GitHub account](https://github.com/signup/free) +- Git installed on your local machine +- PowerShell 5.1 or PowerShell 7+ +- [Visual Studio Code](https://code.visualstudio.com/) (recommended) -- Always [create a new branch](https://docs.github.com/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests) for your work, no matter how small. -- Avoid submitting unrelated changes (bug fixes & new features) in the same branch/pull request. -- Base your new branch off of the appropriate branch on the `dev` repository. +### Learning Resources -### How to submit a contribution -If you wish to discuss ways in which to contribute to the AsBuiltReport project, you may raise an [issue](https://docs.github.com/issues/tracking-your-work-with-issues/about-issues#working-with-issues) within the relevant [repository](https://github.com/AsBuiltReport), or [email us](mailto:support@asbuiltreport.com). +If you're new to Git and GitHub: -#### Creating quality pull requests -A good quality pull request will have the following characteristics: +- [GitHub's guide on Forking](https://docs.github.com/pull-requests/collaborating-with-pull-requests/working-with-forks/about-forks) +- [GitHub's guide on Contributing to Open Source](https://docs.github.com/get-started/exploring-projects-on-github/finding-ways-to-contribute-to-open-source-on-github) +- [Understanding the GitHub Flow](https://docs.github.com/get-started/quickstart/github-flow) -- When you create a pull request, include a summary about your changes in the PR description. The description is used to create change logs, so try to have the first sentence explain the benefit to end users. If the changes are related to an existing GitHub issue, please reference the issue in the PR description (e.g. *Fix #11*) -- It's recommended to avoid a PR with too many changes. A large PR not only stretches the review time, but also makes it much harder to identify issues. In such case, it's better to split the PR to multiple smaller ones. For large features, try to approach it in an incremental way, so that each PR won't be too big. -- Add a meaningful title of the PR describing what change you want to check in. Don't simply put: *"Fix issue #5"*. Also don't directly use the issue title as the PR title. An issue title is to briefly describe what is wrong, while a PR title is to briefly describe what is changed. A better example is: *"Add Ensure parameter to New-Item cmdlet"*, with *"Fix #5"* in the PR's body. +## Using the Issue Tracker -- Please use the present tense and imperative mood when describing your changes: - - Instead of *"Adding support for Windows Server 2012 R2"*, write *"Add support for Windows Server 2012 R2"*. - - Instead of *"Fixed for server connection issue"*, write *"Fix server connection issue"*. -- It will have a title that reflects the work within, and a summary that helps to understand the context of the change. -- There will be well written commit messages, with well crafted commits that tell the story of the development of this work. -- Ideally it will be small and easy to understand. Single commit PRs are usually easy to submit, review, and merge. -- The code contained within will meet the best practices set by the team wherever possible. If in doubt, please [contact us](https://www.asbuiltreport.com/about/contact/). +The issue tracker is the preferred channel for bug reports, feature requests, and submitting pull requests. Please respect the following: -#### Submitting pull requests -**Always create a pull request to the `dev` branch of a repository.** +- **Do not** use the issue tracker for personal support requests. Use [Stack Overflow](http://stackoverflow.com) or community forums instead. +- **Do not** derail or troll issues. Keep discussions on topic and respect the opinions of others. +- Search existing issues (both open and closed) before creating a new one to avoid duplicates. -1. Fork an [AsBuiltReport repository](https://github.com/AsBuiltReport). The example below uses the main AsBuiltReport.Core repository in the command examples. -2. Add `https://github.com/AsBuiltReport/AsBuiltReport.Core.git` as a remote named `upstream`. - - `git remote add upstream https://github.com/AsBuiltReport/AsBuiltReport.Core.git` -3. Create your feature branch from `dev`. -4. Work on your feature. - - Update `CHANGELOG.md` in the repository you have worked in with add / remove / fix / change information - - Update `README.md` in the repository you have worked in with any new information, such as features, instructions, parameters and/or examples -5. Squash commits into one or two succinct commits. - - `git rebase -i HEAD~n` # n being the number of previous commits to rebase -6. Ensure that your branch is up to date with `upstream/dev`. - - `git checkout ` - - `git fetch upstream` - - `git rebase upstream/dev` -7. Push branch to your fork. - - `git push --force` -8. Open a Pull Request against the `dev` branch of a repository. We have Pull Requests templates in all repositories for this project. Please follow the template with each Pull Request. +## Reporting Bugs -Pull requests will be reviewed as soon as possible. +A bug is a demonstrable problem that is caused by the code in the repository. Good bug reports are extremely helpful! -### Reporting Issues and Bugs -GitHub issues is used to track issues and bugs. Report a bug by opening a new [issue](https://docs.github.com/issues/tracking-your-work-with-issues/about-issues#working-with-issues) in the relevant [AsBuiltReport repository](https://github.com/AsBuiltReport). +### Before Submitting a Bug Report -#### Due diligence -Before submitting a bug, or raising an issue, please do the following; +Please perform the following due diligence: -- Perform **basic troubleshooting** steps: - - **Read the documentation.** Ensure you have read the `README` documentation within the relevant report repository. Check the `Supported Versions`, `System Requirements` and `Module Installation` sections. - - **Make sure you're running the latest version.** If you’re not on the most recent version, your problem may have been solved already! Upgrading is always the best first step. - - **Review dependencies.** If the release in question has other dependencies (e.g. vendor PowerShell modules) try upgrading/downgrading those as well. - - **Use `Verbose` parameter.** Add `-Verbose` parameter to the command line to see if the issue can be identified via the output. - - **Disable report InfoLevels.** Edit the report config and set all InfoLevels to 0. Gradually increase InfoLevel values for each section individually, until you are able to recreate the issue. - - **Try older versions.** If you’re already on the latest release, try rolling back a few minor versions (e.g. if on 1.7, try 1.5 or 1.6) and see if the problem goes away. This will help narrow down when the problem first arose in the commit log. -- **Search the open and closed issues within the relevant repository** to make sure it’s not a current or previous known issue. +1. **Read the documentation** - Check the `README` in the AsBuiltReport.Core repository, including Supported Versions, System Requirements, and Module Installation sections. +2. **Update to the latest version** - Your issue may already be fixed in the most recent release. +3. **Check dependencies** - Try upgrading or downgrading vendor PowerShell modules if applicable. +4. **Use the `-Verbose` parameter** - This may help identify the issue. +5. **Test with InfoLevels** - Set all InfoLevels to 0 in your report config, then gradually increase them to isolate the problem. +6. **Try older versions** - If you're on the latest release, try rolling back to see if the problem exists in earlier versions. +7. **Search existing issues** - Make sure it's not a known issue. -#### What to include in your issue report -To make sure your issue gets the attention it deserves, please consider the information requested below as the bare minimum; more information is almost always better! Issues with missing information may be ignored or pushed back to you, delaying a resolution. +### What to Include in Bug Reports -Great issue and bug reports tend to have: +A good bug report should include: - A quick summary and/or background of the issue -- Software versions you are using; - - AsBuiltReport module versions (e.g. AsBuiltReport.Core v1.2.0 & AsBuiltReport.VMware.vSphere v1.3.1) - - PowerShell versions (e.g. Windows PowerShell 5.1) - - Operating System versions (e.g. Windows Server 2016 Version 1607) -- Steps to reproduce the issue; - - Be specific - - Provide the full command line you are executing - - Give sample code if you can - - Upload a screenshot if possible -- What you expected would happen -- What actually happens -- Notes (possibly including why you think this might be happening, or steps you have performed to resolve the issue) - -### Code Contributions - -#### Code Editor -We highly encourage you use the multi-platform code editor [Visual Studio Code (VS Code)](https://code.visualstudio.com/docs) when developing code for AsBuiltReport. - -#### Use a Consistent Coding Style -Code contributors should follow the [PowerShell Guidelines](https://github.com/PoshCode/PowerShellPracticeAndStyle) wherever possible to ensure scripts are consistent in style. - -Use [PSScriptAnalyzer](https://github.com/PowerShell/PSScriptAnalyzer) to check code quality against PowerShell Best Practices. - -✅ DO - -- Use [PascalCasing](https://docs.microsoft.com/en-us/dotnet/standard/design-guidelines/capitalization-conventions) for all public member, type, and namespace names consisting of multiple words. -- Use custom label headers within tables, where required, to make easily readable labels. -- Favour readability over [brevity](https://www.dictionary.com/browse/brevity). -- Use [PSCustomObjects](https://docs.microsoft.com/en-us/powershell/scripting/learn/deep-dives/everything-about-pscustomobject?view=powershell-7) to store data that will be exported to a [PScribo](https://github.com/iainbrighton/PScribo) table. This helps with readability. - - Use the following structure to create tables - - ```powershell title="Creating tables with PSCustomObject" - # Create the PSCustomObject - $myObject = [PSCustomObject]@{ - Name = 'Tim' - Language = 'PowerShell' - City = 'Melbourne' - State = 'Victoria' - Country = 'Australia' - } - # Set the table parameters - Table name, type & column widths - # A list table is set and column widths are evenly set at 50% for each column - $TableParams = @{ - Name = 'User Info' - List = $true - ColumnWidths = 50, 50 - } - # This code snippet must be included for options to show table captions - if ($Report.ShowTableCaptions) { - $TableParams['Caption'] = "- $($TableParams.Name)" - } - # Output PSCustomObject to table using defined parameters - $myObject | Table @TableParams - ``` - -- Set `ColumnWidths` for all tables to improve formatting and readability. Try to maintain a consistent style throughout the report. Cell text will word wrap. List tables should generally use column widths of `50, 50`. -- Sort primary object properties in alphanumeric order. -- Try to perform all safe commands (Get-*, Get API call, etc) at the start of a report script so it can easily be seen what data is being collected. -- Use comments written in English, but don't overdo it. Comments should serve to your reasoning and decision-making, not attempt to explain what a command does. -- Maintain a change log as per [these guidelines](https://keepachangelog.com/en/1.0.0/). The change log should be named `CHANGELOG.md`. - -❌ DO NOT -- Do not include code within report scripts to install or import PowerShell modules. Dependencies should either be documented under the `System Requirements` and `Module Installation` sections of the `README`, or added to the `RequiredModules` section within the report module manifest. -- Do not include functions within report scripts. Individual script files should be created as a private function and be stored in the `\Src\Private` folder. - -### License -By contributing, you agree that your contributions will be licensed under the MIT License. \ No newline at end of file +- Software versions: + - AsBuiltReport module versions (e.g., AsBuiltReport.Core v1.4.3) + - PowerShell version (e.g., Windows PowerShell 5.1 or PowerShell 7.4) + - Operating System (e.g., Windows Server 2022) +- Steps to reproduce: + - Be specific + - Provide the full command line you executed + - Include sample code if applicable + - Upload screenshots if helpful +- What you expected to happen +- What actually happened +- Additional notes (why you think this might be happening, troubleshooting steps you've tried) + +## Feature Requests + +Feature requests are welcome! Please provide as much detail and context as possible about: + +- The problem you're trying to solve +- Why this feature would be valuable +- How you envision it working +- Any examples from other tools or projects + +It's up to you to make a strong case for the merits of this feature. Keep in mind that features should fit within the scope and aims of the project. + +## Pull Requests + +Good pull requests (patches, improvements, new features) are a fantastic help. They should remain focused in scope and avoid containing unrelated commits. + +**Please ask first** before embarking on any significant pull request (e.g., implementing features, refactoring code), otherwise you risk spending time on something that might not be merged. + +### Creating Quality Pull Requests + +A good quality pull request will have: + +- **A meaningful title** describing what change you're making (not just "Fix issue #5") + - Use present tense and imperative mood: "Add support for Server 2022" not "Added support" + - "Fix connection timeout" not "Fixed for connection issue" +- **A clear description** summarizing the changes and their benefits + - Reference related issues (e.g., "Fix #11") + - First sentence should explain the benefit to end users +- **Focused scope** - Avoid PRs with too many changes; split large features into smaller PRs +- **Updated documentation**: + - Update `CHANGELOG.md` with add/remove/fix/change information + - Update `README.md` with new features, instructions, parameters, or examples +- **Well-written commits** that tell the story of the development +- **Code quality** meeting project best practices + +### Submitting Pull Requests + +Always create pull requests against the `dev` branch: + +1. Fork the AsBuiltReport repository + +2. Clone your fork and add the upstream remote: + ```bash + git clone https://github.com//AsBuiltReport.Core + cd AsBuiltReport.Core + git remote add upstream https://github.com/AsBuiltReport/AsBuiltReport.Core + ``` + +3. Create a new feature branch from `dev`: + ```bash + git checkout dev + git pull upstream dev + git checkout -b + ``` + +4. Make your changes and commit with clear messages + +5. Update documentation (`CHANGELOG.md` and `README.md`) + +6. Squash commits into one or two succinct commits if needed: + ```bash + git rebase -i HEAD~n # n being the number of commits to rebase + ``` + +7. Ensure your branch is up to date with upstream: + ```bash + git fetch upstream + git rebase upstream/dev + ``` + +8. Push your branch to your fork: + ```bash + git push --force origin + ``` + +9. [Open a Pull Request](https://help.github.com/articles/using-pull-requests/) against the `dev` branch + +Pull requests will be reviewed as soon as possible. Please follow the PR template provided in the repository. + +## Code Contributions + +### Code Editor + +We highly recommend using [Visual Studio Code](https://code.visualstudio.com/) for development. + +### Coding Standards + +Code contributors should follow the [PowerShell Best Practices and Style Guide](https://github.com/PoshCode/PowerShellPracticeAndStyle) to ensure consistency. + +Use [PSScriptAnalyzer](https://github.com/PowerShell/PSScriptAnalyzer) to check code quality. + +### DO + +- Use PascalCasing for all public member, type, and namespace names +- Favor readability over brevity +- Perform all safe commands (Get-*, API calls) at the start of scripts +- Use comments in English to explain reasoning, not to describe commands +- Maintain a changelog following [Keep a Changelog](https://keepachangelog.com/) guidelines + +### DO NOT + +- Include functions within report scripts (create separate files in `\Src\Private`) +- Submit unrelated changes in the same pull request + +## Version Control Branching + +- Always create a new branch for your work +- Base your branch off `dev` +- Avoid submitting unrelated changes (bug fixes & new features) in the same branch + +## Questions and Discussion + +If you have questions or want to discuss contributions: + +- Raise an issue in the AsBuiltReport.Core [repository](https://github.com/AsBuiltReport/AsBuiltReport.Core) +- Email us at support@asbuiltreport.com +- Visit our website at [www.asbuiltreport.com](https://www.asbuiltreport.com) + +## License + +By submitting a patch, you agree to allow the project owner to license your work under the [MIT License](https://www.asbuiltreport.com/about/license/). \ No newline at end of file diff --git a/LICENSE b/LICENSE index 9f885b7..d8002d2 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2024 AsBuiltReport +Copyright (c) 2025 AsBuiltReport Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index 5bac2f9..10b0933 100644 --- a/README.md +++ b/README.md @@ -18,13 +18,19 @@

+

+ + + + +

- Buy Me a Coffee at ko-fi.com + Want to keep alive this project? Support me on Ko-fi

# AsBuiltReport.Core @@ -37,12 +43,50 @@ The following simple list of instructions will get you started with the AsBuiltR ## :floppy_disk: Supported Versions ### **PowerShell** -This module is compatible with the following PowerShell versions; +The AsBuiltReport Core module is compatible with the following PowerShell versions; | Windows PowerShell 5.1 | PowerShell 7 | | :--------------------: | :----------------: | | :white_check_mark: | :white_check_mark: | +## 🗺️ Language Support +The AsBuiltReport Core module provides UI language support, translating on-screen prompts and messages to match your PowerShell session's configured language. The UI language is automatically detected from your PowerShell session's [culture](https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.utility/get-culture) settings. + +> [!IMPORTANT] +> The AsBuiltReport Core module provides the translation functionality for both core UI prompts and report module content. +> +> Individual report modules provide their own translation files for report-specific content such as headings, text, and tables. +> +> Please refer to individual [report module documentation](https://www.asbuiltreport.com/user-guide/report-modules/overview/) for their language support. + +The module provides intelligent fallbacks for regional language variants. + +For example, 'fr-CA' (French-Canada) will fall back to 'fr-FR' (French-France), then 'en-US'. This ensures that if a specific regional translation is not available, the module will try the parent language, and finally fall back to 'en-US'. + +The module includes comprehensive mappings for: +- English variants (en-AU, en-GB, en-CA, etc.) +- Chinese variants (simplified and traditional) +- French, Spanish, German, Italian variants +- Japanese, Korean, Arabic, and many other languages + +### Languages supported by AsBuiltReport.Core +| Locale Code | Language | Locale Code | Language | +|-------------|----------|-------------|----------| +| **en-US (default)** | English (United States) | **hu-HU** | Hungarian (Hungary) | +| **en-GB** | English (United Kingdom) | **it-IT** | Italian (Italy) | +| **ar-SA** | Arabic (Saudi Arabia) | **ja-JP** | Japanese (Japan) | +| **cs-CZ** | Czech (Czech Republic) | **ko-KR** | Korean (South Korea) | +| **da-DK** | Danish (Denmark) | **nb-NO** | Norwegian Bokmål (Norway) | +| **de-DE** | German (Germany) | **nl-NL** | Dutch (Netherlands) | +| **el-GR** | Greek (Greece) | **pl-PL** | Polish (Poland) | +| **es-ES** | Spanish (Spain) | **pt-PT** | Portuguese (Portugal) | +| **fi-FI** | Finnish (Finland) | **ru-RU** | Russian (Russia) | +| **fr-FR** | French (France) | **sv-SE** | Swedish (Sweden) | +| **he-IL** | Hebrew (Israel) | **th-TH** | Thai (Thailand) | +| **hi-IN** | Hindi (India) | **tr-TR** | Turkish (Turkey) | +| **vi-VN** | Vietnamese (Vietnam) | **zh-CN** | Chinese (China, Simplified) | +| **zh-Hans** | Chinese (Simplified) | **zh-Hant** | Chinese (Traditional) | + ## :wrench: System Requirements The following PowerShell module will be automatically installed by following the [module installation](https://github.com/AsBuiltReport/AsBuiltReport.Core#package-module-installation) procedure. @@ -121,7 +165,7 @@ _Note: You are not limited to installing the module to those example paths, you ### **New-AsBuiltReport** -The `New-AsBuiltReport` cmdlet is used to generate as built reports. The type of as built report to generate is specified by using the `Report` parameter. The report parameter relies on additional report modules being installed alongside the `AsBuiltReport.Core` module. The `Target` parameter specifies one or more systems on which to connect and run the report. User credentials to the system are specified using the `Credential`, or the `Username` and `Password` parameters. One or more document formats, such as `HTML`, `Word` or `Text` can be specified using the `Format` parameter. Additional parameters are outlined below. +The `New-AsBuiltReport` cmdlet is used to generate AsBuiltReports. The type of AsBuiltReport to generate is specified by using the `Report` parameter. The report parameter relies on additional report modules being installed alongside the `AsBuiltReport.Core` module. The `Target` parameter specifies one or more systems on which to connect and run the report. User credentials to the system are specified using the `Credential`, or the `Username` and `Password` parameters. One or more document formats, such as `HTML`, `Word` or `Text` can be specified using the `Format` parameter. Additional parameters are outlined below. ```powershell .PARAMETER Report @@ -137,12 +181,17 @@ The `New-AsBuiltReport` cmdlet is used to generate as built reports. The type of Specifies the password for the target system. .PARAMETER Token Specifies an API token to authenticate to the target system. -.PARAMETER MFA - Use multifactor authentication to authenticate to the target system. +.PARAMETER UseInteractiveAuth + Use interactive authentication (via 3rd party identity provider) to authenticate to the target system. + This parameter has an alias 'MFA' for backwards compatibility. .PARAMETER Format Specifies the output format of the report. The supported output formats are WORD, HTML & TEXT. Multiple output formats may be specified, separated by a comma. +.PARAMETER ReportLanguage + Specifies the language for report content generated by the report module. + Available languages are dynamically determined based on language folders in the selected report module. + By default, the language will be set to en-US. .PARAMETER Orientation Sets the page orientation of the report to Portrait or Landscape. By default, page orientation will be set to Portrait. @@ -161,7 +210,7 @@ The `New-AsBuiltReport` cmdlet is used to generate as built reports. The type of .PARAMETER SendEmail Sends report to specified recipients as email attachments. .PARAMETER AsBuiltConfigFilePath - Enter the full path to the As Built Report configuration JSON file. + Enter the full path to the AsBuiltReport configuration JSON file. If this parameter is not specified, the user will be prompted for this configuration information on first run, with the option to save the configuration to a file. .PARAMETER ReportConfigFilePath @@ -183,7 +232,7 @@ Get-Help New-AsBuiltReport -Full ### **New-AsBuiltReportConfig** -The `New-AsBuiltReportConfig` cmdlet is used to create JSON configuration files for individual As Built Reports. Cmdlet parameters and examples are outlined below. +The `New-AsBuiltReportConfig` cmdlet is used to create JSON configuration files for individual AsBuiltReports. Cmdlet parameters and examples are outlined below. ```powershell .PARAMETER Report @@ -213,21 +262,21 @@ Get-Help New-AsBuiltReportConfig -Full Here are some examples to get you going. ```powershell -# Generate a VMware vSphere As Built report in HTML & Word formats. Perform a health check to highlight particular issues which exist within the VMware vSphere environment. Save the report to the 'H:\Documents\' folder. +# Generate a VMware vSphere AsBuiltReport in HTML & Word formats. Perform a health check to highlight particular issues which exist within the VMware vSphere environment. Save the report to the 'H:\Documents\' folder. New-AsBuiltReport -Report 'VMware.vSphere' -Target '192.168.1.100' -Username 'admin' -Password 'admin' -Format HTML,Word -EnableHealthCheck -OutputFolderPath 'H:\Documents\' -# Generate a Nutanix Prism Element As Built Report using specified username and password credentials. Specify the report configuration file to be used. Export report to Text, HTML & DOCX formats. Use the default report style. Save the report to the '/Users/Tim/Documents' folder. Display verbose messages to the console. +# Generate a Nutanix Prism Element AsBuiltReport using specified username and password credentials. Specify the report configuration file to be used. Export report to Text, HTML & DOCX formats. Use the default report style. Save the report to the '/Users/Tim/Documents' folder. Display verbose messages to the console. New-AsBuiltReport -Report 'Nutanix.PrismElement' -Target 'prism.nutanix.local' -Username 'demo' -Password 'demo' -Format Text,Html,Word -OutputFolderPath '/Users/Tim/Documents' -ReportConfigFilePath '/Users/Tim/AsBuiltReport/AsBuiltReport.Nutanix.PrismElement.json' -Verbose -# Generate a Pure Storage FlashArray As Built Report in Text format and append a timestamp to the filename. Use stored credentials for authentication. Use the default Pure Storage report style. Save the reports to the 'H:\Documents' folder. +# Generate a Pure Storage FlashArray AsBuiltReport in Text format and append a timestamp to the filename. Use stored credentials for authentication. Use the default Pure Storage report style. Save the reports to the 'H:\Documents' folder. $Credentials = Get-Credential New-AsBuiltReport -Report 'PureStorage.FlashArray' -Target '192.168.1.100' -Credential $Credentials -Format Text -Timestamp -OutputFolderPath 'H:\Documents\' -# The following creates a Cisco UCS Manager As Built report in default format (Word) with a customized style. -New-AsBuiltReport -Report 'Cisco.UCSManager' -Target '192.168.1.100' -Username 'admin' -Password 'admin' -StyleFilePath 'C:\scripts\ACME.ps1' -OutputFolderPath 'H:\Documents\' +# The following creates a Microsoft Active Directory As Built Report in HTML format with Spanish language content. +New-AsBuiltReport -Report Microsoft.AD -Target dc01.corp.local -Username 'CORP\admin' -Password admin -Format HTML -ReportLanguage 'es-ES' -OutputFolderPath 'H:\Documents\' -# The following creates a Nutanix Prism Element As Built report in HTML format, with a custom filename. -New-AsBuiltReport -Report 'Nutanix.PrismElement' -Target '192.168.1.100' -Username 'admin' -Password 'admin' -Format HTML -AsBuiltConfigFilePath 'C:\scripts\asbuilt.json' -OutputFolderPath 'H:\Documents\' -Filename 'My Nutanix Configuration' +# The following creates a Veeam Backup & Replication As Built Report in HTML format with a custom filename. +New-AsBuiltReport -Report Veeam.VBR -Target veeam01.corp.local -Username admin -Password admin -Format HTML -Filename 'Veeam-Backup-Report' -OutputFolderPath 'H:\Documents\' ``` ## :x: Known Issues diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 0000000..49fed73 --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,57 @@ +# Security Policy + +Thanks for helping make AsBuiltReport safe for everyone. + +## Security + +AsBuiltReport takes the security of our software products and services seriously, including all of the open source code repositories managed through our GitHub organizations, such as [AsBuiltReport](https://github.com/AsBuiltReport). + +While AsBuiltReport is an open source project without a formal bug bounty program, we are committed to addressing security vulnerabilities promptly and will ensure that your findings are passed along to the appropriate maintainers for remediation. + +## Reporting Security Issues + +If you believe you have found a security vulnerability in any AsBuiltReport repository, please report it to us through coordinated disclosure. + +**Please do not report security vulnerabilities through public GitHub issues, discussions, or pull requests.** + +Instead, please send an email to support@asbuiltreport.com with the subject line "SECURITY: [Brief Description]". + +Please include as much of the information listed below as you can to help us better understand and resolve the issue: + + * The type of issue (e.g., code injection, credential exposure, or privilege escalation) + * Full paths of source file(s) related to the manifestation of the issue + * The location of the affected source code (tag/branch/commit or direct URL) + * Any special configuration required to reproduce the issue + * Step-by-step instructions to reproduce the issue + * Proof-of-concept or exploit code (if possible) + * Impact of the issue, including how an attacker might exploit the issue + * Affected versions of AsBuiltReport modules + +This information will help us triage your report more quickly. + +## Response Timeline + +We aim to: + * Acknowledge receipt of your report within 72 hours + * Provide an initial assessment within 7-10 days + * Keep you informed of our progress throughout the remediation process + +## Disclosure Policy + +We follow coordinated disclosure principles: + * Security issues will be addressed in a timely manner + * We will coordinate with you on the disclosure timeline + * Public disclosure will occur after a fix is available and deployed + * We will credit reporters (unless anonymity is requested) + +## Supported Versions + +Please refer to individual module repositories for information on which versions are currently supported with security updates. + +## Security Best Practices + +When using AsBuiltReport: + * Store credentials securely using appropriate credential management solutions + * Review generated reports before sharing to ensure no sensitive information is exposed + * Keep AsBuiltReport modules updated to the latest versions + * Follow the principle of least privilege when providing credentials to AsBuiltReport \ No newline at end of file diff --git a/Samples/AsBuiltReport.Sample.Style-1.ps1 b/Samples/AsBuiltReport.Sample.Style-1.ps1 deleted file mode 100644 index 1697f14..0000000 --- a/Samples/AsBuiltReport.Sample.Style-1.ps1 +++ /dev/null @@ -1,131 +0,0 @@ -# Sample Document Style 1 - -# Configure document options e.g. page size, margins, default font, page orientation -# It is recommended to use a web safe system font. If the configured font is not installed on the -# system from which the report is viewed then a substitute font will be used. This may not result -# in the desired look of the document -DocumentOption -EnableSectionNumbering -PageSize A4 -DefaultFont 'Trebuchet MS' -MarginLeftAndRight 71 -MarginTopAndBottom 71 -Orientation $Orientation - -# Title & Heading Styles -Style -Name 'Title' -Size 24 -Color 'F30E0D' -Align Center -Bold -Style -Name 'Title 2' -Size 18 -Color '223F8C' -Align Center -Style -Name 'Title 3' -Size 12 -Color 'FDDA00' -Align Center -Style -Name 'Heading 1' -Size 16 -Color 'F30E0D' -Style -Name 'Heading 2' -Size 14 -Color '223F8C' -Style -Name 'Heading 3' -Size 12 -Color 'FDDA00' -Style -Name 'Heading 4' -Size 11 -Color '6BADE6' -Style -Name 'NO TOC Heading 4' -Size 11 -Color '6BADE6' -Style -Name 'Heading 5' -Size 10 -Color '6BADE6' -Style -Name 'NO TOC Heading 5' -Size 10 -Color '6BADE6' -Style -Name 'Heading 6' -Size 9 -Color '6BADE6' -Style -Name 'NO TOC Heading 6' -Size 9 -Color '6BADE6' -Style -Name 'NO TOC Heading 7' -Size 9 -Color '6BADE6' -Italic -Style -Name 'Normal' -Size 10 -Color '000000' -Default -# Header & Footer Styles -Style -Name 'Header' -Size 10 -Color '000000' -Align Center -Style -Name 'Footer' -Size 10 -Color '000000' -Align Center -# Table of Contents Style -Style -Name 'TOC' -Size 16 -Color 'F30E0D' -# Table Heading & Row Styles -Style -Name 'TableDefaultHeading' -Size 10 -Color 'F30E0D' -BackgroundColor 'FDDA00' -Style -Name 'TableDefaultRow' -Size 10 -Color '000000' -Style -Name 'TableDefaultAltRow' -Size 10 -Color '000000' -BackgroundColor 'EAEAE6' -# Table Row/Cell Highlight Styles -Style -Name 'Critical' -Size 10 -Color 'FFFFFF' -BackgroundColor 'F30E0D' -Bold -Italic -Style -Name 'Warning' -Size 10 -Color 'FFFFFF' -BackgroundColor '223F8C' -Bold -Italic -Style -Name 'Info' -Size 10 -Color '000000' -BackgroundColor 'FDDA00' -Bold -Italic -Style -Name 'OK' -Size 10 -Color '000000' -BackgroundColor '73BF1F' -Bold -Italic -# Table Caption Style -Style -Name 'Caption' -Size 10 -Color '000000' -Align Center - -# Default Table Style Properties -$TableDefaultProperties = @{ - Id = 'TableDefault' - HeaderStyle = 'TableDefaultHeading' - RowStyle = 'TableDefaultRow' - AlternateRowStyle = 'TableDefaultAltRow' - BorderColor = 'F30E0D' - Align = 'Center' - CaptionStyle = 'Caption' - CaptionLocation = 'Below' - BorderWidth = 0.25 - PaddingTop = 1 - PaddingBottom = 1.5 - PaddingLeft = 2 - PaddingRight = 2 -} - -# Table Styles -TableStyle @TableDefaultProperties -Default -TableStyle -Id 'Borderless' -HeaderStyle Normal -RowStyle Normal -BorderWidth 0 - -# Cover Page Layout -# Set Header & Footer, if enabled in report JSON configuration -if ($ReportConfig.Report.ShowHeaderFooter) { - Header -Default { - Paragraph -Style Header "$($ReportConfig.Report.Name) - v$($ReportConfig.Report.Version)" - } - - Footer -Default { - Paragraph -Style Footer 'Page ' - } -} - -# Set position of cover page image, report titles and other information based on page orientation -if (-not ($ReportConfig.Report.ShowCoverPageImage)) { - # If cover page image is disabled, set report title position - if ($Orientation -eq 'Portrait') { - BlankLine -Count 20 - $LineCount = 25 - } else { - BlankLine -Count 10 - $LineCount = 15 - } -} else { - if ($Orientation -eq 'Portrait') { - $LineCount = 19 - } else { - $LineCount = 1 - } -} - -# Show Logo image, if enabled in report JSON configuration -if ($ReportConfig.Report.ShowCoverPageImage) { - Try { - Image -Text 'Sample 1 Logo' -Align Center -Percent 100 -Base64 "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AAAAQ3B0bmJvb2wAAAAAAENsYnJib29sAAAAAABSZ3NNYm9vbAAAAAAAQ3JuQ2Jvb2wAAAAAAENudENib29sAAAAAABMYmxzYm9vbAAAAAAATmd0dmJvb2wAAAAAAEVtbERib29sAAAAAABJbnRyYm9vbAAAAAAAQmNrZ09iamMAAAABAAAAAAAAUkdCQwAAAAMAAAAAUmQgIGRvdWJAb+AAAAAAAAAAAABHcm4gZG91YkBv4AAAAAAAAAAAAEJsICBkb3ViQG/gAAAAAAAAAAAAQnJkVFVudEYjUmx0AAAAAAAAAAAAAAAAQmxkIFVudEYjUmx0AAAAAAAAAAAAAAAAUnNsdFVudEYjUmx0QLQ//7gAAAAAAAAKdmVjdG9yRGF0YWJvb2wBAAAAAFBnUHNlbnVtAAAAAFBnUHMAAAAAUGdQQwAAAABMZWZ0VW50RiNSbHQAAAAAAAAAAAAAAABUb3AgVW50RiNSbHQAAAAAAAAAAAAAAABTY2wgVW50RiNQcmNAWQAAAAAAAAAAABBjcm9wV2hlblByaW50aW5nYm9vbAAAAAAOY3JvcFJlY3RCb3R0b21sb25nAAAAAAAAAAxjcm9wUmVjdExlZnRsb25nAAAAAAAAAA1jcm9wUmVjdFJpZ2h0bG9uZwAAAAAAAAALY3JvcFJlY3RUb3Bsb25nAAAAAAA4QklNA+0AAAAAABAAR///AAIAAgBH//8AAgACOEJJTQQmAAAAAAAOAAAAAAAAAAAAAD+AAAA4QklNBA0AAAAAAAQAAAB4OEJJTQQZAAAAAAAEAAAAHjhCSU0D8wAAAAAACQAAAAAAAAAAAQA4QklNJxAAAAAAAAoAAQAAAAAAAAACOEJJTQP1AAAAAABIAC9mZgABAGxmZgAGAAAAAAABAC9mZgABAKGZmgAGAAAAAAABADIAAAABAFoAAAAGAAAAAAABADUAAAABAC0AAAAGAAAAAAABOEJJTQP4AAAAAABwAAD/////////////////////////////A+gAAAAA/////////////////////////////wPoAAAAAP////////////////////////////8D6AAAAAD/////////////////////////////A+gAADhCSU0EAAAAAAAAAgABOEJJTQQCAAAAAAAEAAAAADhCSU0EMAAAAAAA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ZW50IyIgeG1sbnM6cGhvdG9zaG9wPSJodHRwOi8vbnMuYWRvYmUuY29tL3Bob3Rvc2hvcC8xLjAvIiB4bWxuczpkYz0iaHR0cDovL3B1cmwub3JnL2RjL2VsZW1lbnRzLzEuMS8iIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoTWFjaW50b3NoKSIgeG1wOkNyZWF0ZURhdGU9IjIwMTUtMDUtMDVUMTU6MjA6MTArMTA6MDAiIHhtcDpNZXRhZGF0YURhdGU9IjIwMTUtMDUtMDVUMTU6MjA6MTArMTA6MDAiIHhtcDpNb2RpZnlEYXRlPSIyMDE1LTA1LTA1VDE1OjIwOjEwKzEwOjAwIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOkVCMTQyNDc1RTQyMTY4MTE4MDgzRUYwNEFFRjREQjMwIiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOkVBMTQyNDc1RTQyMTY4MTE4MDgzRUYwNEFFRjREQjMwIiB4bXBNTTpPcmlnaW5hbERvY3VtZW50SUQ9InhtcC5kaWQ6RUExNDI0NzVFNDIxNjgxMTgwODNFRjA0QUVGNERCMzAiIHBob3Rvc2hvcDpDb2xvck1vZGU9IjMiIHBob3Rvc2hvcDpJQ0NQcm9maWxlPSJzUkdCIElFQzYxOTY2LTIuMSIgZGM6Zm9ybWF0PSJpbWFnZS9qcGVnIj4gPHhtcE1NOkhpc3Rvcnk+IDxyZGY6U2VxPiA8cmRmOmxpIHN0RXZ0OmFjdGlvbj0iY3JlYXRlZCIgc3RFdnQ6aW5zdGFuY2VJRD0ieG1wLmlpZDpFQTE0MjQ3NUU0MjE2ODExODA4M0VGMDRBRUY0REIzMCIgc3RFdnQ6d2hlbj0iMjAxNS0wNS0wNVQxNToyMDoxMCsxMDowMCIgc3RFdnQ6c29mdHdhcmVBZ2VudD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoTWFjaW50b3NoKSIvPiA8cmRmOmxpIHN0RXZ0OmFjdGlvbj0ic2F2ZWQiIHN0RXZ0Omluc3RhbmNlSUQ9InhtcC5paWQ6RUIxNDI0NzVFNDIxNjgxMTgwODNFRjA0QUVGNERCMzAiIHN0RXZ0OndoZW49IjIwMTUtMDUtMDVUMTU6MjA6MTArMTA6MDAiIHN0RXZ0OnNvZnR3YXJlQWdlbnQ9IkFkb2JlIFBob3Rvc2hvcCBDUzYgKE1hY2ludG9zaCkiIHN0RXZ0OmNoYW5nZWQ9Ii8iLz4gPC9yZGY6U2VxPiA8L3htcE1NOkhpc3Rvcnk+IDxwaG90b3Nob3A6RG9jdW1lbnRBbmNlc3RvcnM+IDxyZGY6QmFnPiA8cmRmOmxpPkFDRjJBOUVGODQ3MjlEQTY1RDYzM0Q1NjdCMjE2MTBDPC9yZGY6bGk+IDxyZGY6bGk+QjE0NDdFMDBGQ0MwOUNFMzRCMEY3MjQxMzhBQjQzOTQ8L3JkZjpsaT4gPC9yZGY6QmFnPiA8L3Bob3Rvc2hvcDpEb2N1bWVudEFuY2VzdG9ycz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPD94cGFja2V0IGVuZD0idyI/Pv/iDFhJQ0NfUFJPRklMRQABAQAADEhMaW5vAhAAAG1udHJSR0IgWFlaIAfOAAIACQAGADEAAGFjc3BNU0ZUAAAAAElFQyBzUkdCAAAAAAAAAAAAAAABAAD21gABAAAAANMtSFAgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEWNwcnQAAAFQAAAAM2Rlc2MAAAGEAAAAbHd0cHQAAAHwAAAAFGJrcHQAAAIEAAAAFHJYWVoAAAIYAAAAFGdYWVoAAAIsAAAAFGJYWVoAAAJAAAAAFGRtbmQAAAJUAAAAcGRtZGQAAALEAAAAiHZ1ZWQAAANMAAAAhnZpZXcAAAPUAAAAJGx1bWkAAAP4AAAAFG1lYXMAAAQMAAAA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fuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvdf//Q3+Pfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3XCSSOGN5ppEiiiRpJJJGVI40QFmd3chUVVFySQAPe1BZlVQSxNABxJPAD5nrRIAJJoB1XL8if5tX8v34xvkcb2D8i9n53d+Ogllfr3q16jtPfEksTSp9nLh9kxZeHEVTywsg/iM9FGrD1OoBPsy3HbP3Bbx3vNu5Wey2LkgPfzJbE0FeyJ/8Yk+XhQvXqQvbv2j92Pd69Xb/av2z3zmG5JFTZWskkKg/ia5YJbKo8y0wp1Qv8kf+FNO+MtJTYv4ifHek2zS0W6MTWVe9vkJloKus3FtPG5Whq8phsd1/sirqF29V7pxsU9IK6pzFRLjRL5hSSyKFEY3vvr7M7Dc+DDFvHMlUozWqLYW8bMpBZJbtWmnMRoVQ20KyEULgHrpH7Z/3OH3mOc7Btw9wubdh5NBjLRQOW3O5duKLKsDRQwI2A5EssiUNFNBWz34ffz9Phb8kpMdtTtTI1fxU7UrZYKOLb3bmRoRsHOV0w0qu1O26RYdq1Ecjg6IssMPWm4AgYn2NeWN35S5+jibkHmWO+3Blq1jMv024xkCpX6Z2IuKD8VnJcA5wvWHPv59zX7xv3bLm5f3K9vZ5OV0YhN228Ne7bIuKM8sa+JalhVilzHGEHFz1d/RVtHkqSlyGOq6avoK6nhq6Ktop4qqkrKSojWWnqqWpgd4ainnicMjoxVlIIJB9qpYpYJZIJ4mSdGIZWBDKQaEEGhBBwQcjrF6OSOVFkicNGwqCCCCPUEYPQY94d39XfHHqveXdHc278bsfrjYeKky+4tw5NnZYow6QUlBj6OBJa3LZvL1ssdLQ0NNHLVVlVLHDCjyOql+yspb+cwxPGkaozySSMEihiQFpJZZGoscUags7sQFUE9K7Oyv90v9v2jaNunvN5vJ0gt7eBDJPcTyHTHDDGuXkc4AHDLMQoJGvT0z/wAKbPjxujeWbw3d3QvafUWzJty1dLszfuAqsZ2XGu1pa3xYTJdkbUxUWM3JtPMS4/8AymsgxkWdgpr6FlcrchKy9yfZ7eLx9vsOens7gOyRy7jbS21peaKhprW5TxVWJmoEW6W3ehBfSTpGenOf92P98Dk/ljb+ZbTkqx352tUmvLHbLyObcdueRdYtri1kMZlkVcu8DstcKppm9j4/fMf4tfKnHNkvj13x1t2r4Y3mrMVtnclG+58XHH4/K2Z2hWtR7pwvjMyhvuqOGxYf19je52TdLWyh3NrYSbTKAUuImSe3cHhpnhZ4STTgHr6jrBTe9m3rljdZ9h5o2S92zfIjRre7gltpgQKn9OZEY0HEqCPn0ZX2VdF3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691//9Hf49+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3XvfuvdNGez+C2thsnuLc2axO3Nv4WjmyOYzueyNHiMNiaCmQyVFdk8pkJqehoKOBBqeWV1RBySB7etra5vJ47Wzt3luXNFRFLMx40CqCTjOB1V3SMapHCrUCpNMkgAfaSQAPMkAda13zf/4UX9T9fnMdf/CTAUHem8I0qKGXufcYrsf0ngawp4/uNt0sRotwdqT0sj3VqVqDDyFLpXTC6kD87e5XJvt9JPt95P8AvbmyM0NlayoY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MU1W7x0sUkqJLUyRxPPJHTxswad44ImdgoJCKSeB7sFZgzKpKqKn5Dhn0yQPt60SBSp49Z/det9e9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvdf/S3+Pfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3XRIH1IHIHP9SbAf65Pv3WiQMk0/wBnrv37rfSF7Q7I2j071vv3tjf+UiwmyOtdn7j3zu3LSldNBt7a2Jq81lqhVZk8syUVG/jjB1SPZV5IHtbt1hPul/Z7dbU8eaRUBOFGo01Mc0VR3M3BVBJwOvaZXKx28LS3LsFRFy0jsQqRoPN3YhEHEsQBk9fNe+d/8yn5U/PfdVJN2xvqTZ/VWazmQqNk9JY15cZ1psjDK9XXYGHc+IhqIV7E7FjxsyRyZDMTzQrVRu1HBAgWMxZa+4c3P8furbct7VfXHt9sFsrCw2tnj3Pfo3uBa+PdXarLcw7ahUz3UFnEoSKREcEkzj6Avbr7lfIv3Vdr9gNz5nutlT365xndJd+3+JbnaeWnSzF21rt+3zGG0l3abUbeykvpRqmjkYaiiROWDH0bQPtvAR0+R3HuDdOXxW1sHTY3HGsr9ybjztVHSYnF0UFIi08M2TrJ1ihuY4yxF2HvGzlT235l94ub902L2y5atYd00S3Edh9YkKW0MArKqSX0iyzvGoLuhLzkEnQaddMPcf3u5P8Au3e2Oy84++XuLfz7BbmOGTd/oJJjcSyksk08W1wvb20ctdMb6UthQLrB6vt/lP8AwS/mGfH753fG7vTdPxM7F2l1vDk99bK7Dzu7q7ZuEk2/sjduzc1ia7LVmFk3YdyJHSZ+LHTxR/ZSGoEPpFiHGQPs37c848gb7zdLzLc7fHs17tBiYQ3aTlp45ori3KrGCHOqMxnICLIxJqKHkR/eS/fD+6995r2Q5d5a9t+Z7679wNp3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f93j93j2y+8D7ie423+8t5aW3INny60CSzXCWzJue4yiCyktZJGQfVweHI8KgklmAKkEA2Y/ynf5rOyv5gnX8mzt7Lh9h/K7rvEU0nZXXlPP4cbvHFxGGjHavWEdTI1TX7Oy1Uyito7yVWBrZRTVBeN6Wpql/L/MHL3PnLsXOXJ7t+7CVS5tmOqbb7hhXwJiPiichja3NAs8YIISZJY0gP7zv3ZPcf7qPuXde3nP9sZtvmLybZuSKRb7laqcSIaaUuYwQLm34xv3KDGRS4X2s6x4697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuv/T3+Pfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3XvfuvdFS+a/y32J8Hvjnvf5G9hYrLbjwu0KjbeModp7eqMXTbi3ZuDdm4sZtnCYLBvmayhx33k1XkxNIZJAI6WGWQ3CH2ohS1WHcb/crv6faLK1lubiXSX8OGFC7sEBBdjQIigjU7KtRWvQs5D5I5k9zOd+Uvbvk6yW45r3u/jtLSNm0I00taeJIQRHGoBZ3IOlQTQ8OtTDvr/hSl8tOwZ6rA/H/rHqf4+0k/m+2yW56yfuLsn7WaGWOCWCinj2xs/H1cbFZQTRZSIFQDdb3ifc/fPYrPZ59/5Q9rd53bY42CNuN+HtNuSTVpoVtVkJ1GihXvY2rgqT1159sf7oS1l5i27lr32+8psm282zRNJ+5NnaGbcSmjWe66cOQijUZIrQqUOqq4pTh2/8nPlj8gMtHnu6/kl3T2FkKeoFZQU9d2Hmtv4LDVSvHJDLgtpbOn29tXD1NNLCGhmgpFqIm9Qk1Ekwruv3jPd3eJq7ZzH+6LNJAwh2q3jtEBHDxJAGnmUj4kmldHGGUjHXTD27/u7/ALkntpZXFnH7QQ79fTRNHJd7xJJfzMjqA4TxG8OIHJUxxq6EnQwx1aL8M/5+Xy8+Mpxey++aef5ZdT0E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917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r/1N/j37r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Wrv/AMKd+4mw3THxm6Epa8wf6Q+0Nxdo7mpWo4Hgl2z1JtwUdHLNkpuaAw7r31QyhUt5VhfUQq8gn3buprH2l5htrS3eTc96v7LbIFj1NI5kl+plRI1y7OLeNAKGpfSMt10m/upOTLLmL72VtznvbpFy1yZsF9u1zNIypFAxT6aCWR2wqoJJ3YkgKF1EgCo1C/jP0/vfvvuLZHT3V2Kp6jd/cPYuO21sHL5hJKZpDuETVmY3BnpRFLkYtubWxcFTWmQ2lkxtKQqAhS4P5p5dn9wOavbD2y3PnGW03W02XweYLGzdrjbNpXbEARoIkdbV72WJV+st0DxxbixBmZ5GWPqltvuvy793D2a+8f8AeUl9tIdx5Nm35rzlTc9xhW13vmB95dmeC4mkR7yOwiuX0bbeSmN59r0f4uscStLfpur/AITifPrA19LFtPsv43dgUUtO71NdVbl35spqWqDMFgOPrdlblM8ToFPkSYFSbWNuS6X7tWwO08m2e6E8A8QhVuNuBYp5Etb3RWvqCCPTrGnZP76fYXiSLm/7tNz4pQEvt+6xEB/MAXUMZK+hND6j0om3Tt3Nbb3DvDY+6MeuI3j1/uvc2y9x41KmOthodybPzlft7OQUlfGqJWY9sljZPBMFUSwsj2F/cA8/8r3XIPOO+8nbpew3V7YzInjxKyxTxSxpKkiq/coaORTpbINQeuuPsX7q7P7w+1/t57zcr2dza8v8xWQuI4JypngIdo3imKVQyRupGpcEcOtwH/hM13Yu4/jd3l8fK6oLV3TvbC702/DNPEZDs7uHHvlGjpKbytMtJRb0wGWZ20KnkqxySTbMT2s3luYfablCeWVnvNqefbJSQTRYH8e1q3AkwXARQOCwgDgevnE/vUfbH/W6++BzXvFrb+Hs/Ntjb7vF2hQ0xUW15SnpLEjE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zu3AYmCQMMFWx0mQSCMvTVsoX7dgXtXuTyRzJsd7zBNewpstrKkU1zBazW8m3GU6LX95WDS3TyWc7Dw03OzmkaOVliu7Yu6N1L/vd/dpc0cubztXK3tttl1Ye4M9hLPa7bfX6X1nv/0qeJdrs+7eDb/T7rbp+rJtV9CiTQq0tnNoWTRuYfHH5O9E/LTrTGdtfHzsfAdkbKyLGmnq8RO0eUwGWiVWq9vbswFYlPm9q7joCwE1DXwQVCAhtJRlZhTe7fPZC2kZo5bKeMSQzxOssE8Z4SQyoSkiH1UnSaqwVgVHLjedm3rlzeNz5d5k2a727mKylMVxa3MTwzwSLgpJG4DA+hFVYZRmWh6Hr2h6Luve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuv/1d/j37r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3TLnty7d2tj6nLbmz+F25iqKB6msyeeytDiMfSU0QLSVFTW5CenpoII1UlnZgoA5PtVa2N9fyCKxs5ZpT+GNGc/sUE9MS3VtblRPcIhPDUwFa8KVIrXy6g7P3xsvsLCxbk2Du7bG99uz1FRSQ57aOfxW5MLLVUcniq6aLKYarrKF56WQaZEDlkbgge63Vnd2MzW97ayQ3A4q6lWH2hgD0/QjiCD8wQf2H1GR8s9Kj2n691pa/8KgOrt61Hfvx27Iy6TydU7u6W3N1Pgq+nL+PC7+w26cluzceOqiS0MVZuTbWYoqil9P78eHqQ1xDb3Gnu/vPMPK20+2nPuwxxy2/L3MRuJopNRQyypAbZ5AtKRkW80OsMGjZwVIZ1PXX/APulrL285+vPvNewvNd1La8yc4csxx288ZVZDZReNHdRwk1DSwyTx3DIwKOhowKhh0Ub/hOpvDp/HfzCqRO5MlSY7fUnXm9tifH3IyaKbbme7NrJaGTctExlLJj91VvX1HWQ4yIsEmc10EbNI0Mbnftty1ybs95zje8sNcw75vmy2G6Q2N2VkubTa55ZpLuJ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uJGkZa1NQmoRpk0RVHl0ZIkAXJAAubk24H1P+w9pMnhx6IiQAWJoo6+bZ/Oj+b2N+bPzM7LqMRnJKjqXqXG5fpXpiSCCqq8JLhsNlpU3n2BUz09L4Yqfs3fVBKKeR9QqcLi6FgbH2G+YE5vuee+QrvlXare85c5U3hTdQtdW0Nzfbmyq16tjBNOpuX2m2eGItGP0bkyEHvNO2v3Nvbz279rvuze5UXuRu13tXup7n8vNNBciwvZ7Xadm1Ou0JutzbQypZx7xdRyy+FPRpYcU06dQI/Ez4Z/Kj5sy42P46dLbk3djvMuPzG9quKLavV20K8U5NdR5nfubWnw8U1EqMslFQ/e5EKVApiXUHH+f7vXO39a+Z9qjuIrfleO+lUbjcysIryJZqxyxxR6pb16MCxRWiWVXBmFCR0C5y/vJPu1+2Ptv7f75zm7T+6MmzwTDYLG3SW+sJnhVJIpGcLHt0bFSEMzQu0OgmMAgdBj8kPj32l8c+5N0dCdu4bHbf7A6u3ZjW3JHSV9Rk8XV498eMtgtwbPyM1BjZ8vhN1Yuthkp6h4ItMUssciCWN0Wl3tVp7L7/wC42y7zuE24Dc+V5rbbZIofDgv1vnjUzXCs7+Atk0UhMdXcXUKgEDPQk9vvdm3+/L7bewXuX7cbVbbfabVzxBf7zDdXAku9mfa0mJtYRGB40194kcayjTE1pNI1GBp1ej/wmx7ij2T8zu2+namojpqDvrpVc7QUq00pNbvHprOLVUzNPF/k8Up2hvPJEmQapEpkUNaMD2O/u47o0/J/PXKUktTYXltfwgscR3CtbXOhTgDxVtidNMnPl1z9/vtPbmGLefY33isNvjRrxLzaruRUAZmjC3Vs0zgVcqiyxxlySFqq4oOt3/3NnXCfr3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r//W3+Pfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3VD/8+bZHy6ofjhQ/If4r9+91dbY7phcie8+uOq9yTbdj3d1ZmpaL7/sBavFRR7hiy3V9TTLU1S01Qiy4KetkZS1NGr+3W85qi5R3+HkP6SPnOIfU27S2sN086xI/jWkazpIiSSIfFhcJqMsIhGZgVyK+6j/rE3Hvrydsn3j9ga+9rt1kFlI4uZrZbK5mdRa3UphZGkt/FpDOhJAWRZKURq6G3Ye/94bzzkcG+N5bh33XZqhEsuZ7c37u3dlHkBS1RkhxcMm467NJPVpNK0yRkoqatSqSTaAeUeY/dL3R5J37nLmj3O5uu7Xbr1LRtv2JFNzDFNEXN7cQxSQBbKo8DUsUlZKq7IANX0P87e2v3dvu6+5fJ3tz7X/d+9s9nvN12mS9TdeYyYbK5khnWEbdZzvBcCXcipFyweWMiEq6LKS2jZ2/4TP/ACwm2b2R2Z8Lt3TRUGI7Ux1X3N1PQR1glxmN3ztWjpMX2RtzFoYadQd0bSiocvGiKoDYmscgs5Yjv2j5j2ne+XuZOULDebq9bl25ElrNdRiC5n2+7f8AVWWLXKQ1nfsymsjEi6B7VUKOY396v7D73yxv3td94q45W27a/wCtVn9Buttt0wuLGDcrRWazmgnEVuHivrEfEYg3iQqlWPc25n7kPrkf1Xz/ADQviDF82Phj2v1BjaSGXsXG4+PsTpurkIR6TtXY6TZbbNGJyyeCk3SgnwlYxNhRZKU/UAjcu2bdzBt+78rby6rs+6WzW0rkVERehinp6286xzjzPhleBIMney3uvvvsX7s8ge7vLmo7lsW4x3DRqT/jFsTou7YgZYT27SRhagFyhJGmvXzOaOfcewaqkz2Eqsrg3xO6aLOUT0002D3511vOkz8NRDWYasi1NDmts7piEyRvonpamIqGbQFGP+wX83MnPe3W15Lc8v8A3heW4JLZL1NM+2X/AO57Z1Ee4wkiS1aS0g+lkmi8a0uY9JlgUyOT9MXN2y7ZtHspu9/aW2285fcs5/uIrqTbZG8Detr/AKyXaNK+1TqJLfcEiv7tryO1n8K8tpNaRXMqxog+hr/LH/mtdafKT4j5zsTv3fOzes+1vjpi6HEfJOs3HlMdtfbphhoGfDdvY166oipaXa3YVLSSSiJGP2eWiqqFQ3iiaXIjlu5tfcrZtm5u5H2+Rtv3AlXt172srtAGuLSRsUSMESwzSaQ9q6SMQyyhPnG+8393zm37rXvJv/tDzdrnVHEu13QUn96WErEW00SLqL3GPBuIY9bLcKQFAkQHT2/mW/IzrD5QfPj5B99dO11fleqN3NsPGbQzeSwdXt+r3PLs3r/b2z8znqPFV8UGThwuVyeGd6GWsip6ien0yNEgZR7xU+8du3LW7c08oQ8sbzFf7jtu1fTX0sTeJbLOLy5mSKGb4J/CimVZXhLQ+ICsbuBqP0H/AN1v7Se7ntd92nedn90OU5Nm/e/ML7jt9tOVW7FpPbxK011CO6AySKWjif8AV0UZ1UtToZP5NXxO3v8AKv5z9a7gxFTlNu7E+OG5Ntd6dk7zxgZJsfNt3KfdbC2Pjax18SZjf2ex7QyrcsmFpq97avHdV93ble6bf733BmJXadpjmto6jF1eXkLxNFw7o4IHeab0YwxmniAgI/3t/vzy1yF7CWv3fIYILznbnEpIyMRqsdvtZkke9oMrNJMqwWxrWrO9CqN1tKfz2qDvbsL4b4j46/HjqjsntjfPyI7c2Ts7LYzr/a65qkxOx9qS1PZG4a3d+crKmhwuzcHX1W0qOiFdW1EELSVAj1jV7yav9q3bdeT+fINhaz/fUm2NbxCedIAPq5I7aWRS5GoxW8szFV1NwIVuuEv3WOZPbjkz7w3tVzr7s7lLa8h7JuH7wuDHBJcPI9rG8kECxRguzST+GRQUAQnjQGkj47f8Jtvk/v4UGX+SXa2xegsJJNer2rsuFe1+xpKXxF1VsoJsRsLb9WZiF1LLm0C6rpe14E5Z+7ry7tsUL85c2XN/Iqg/T2C/TxA6vga7nRpmXTx0WyZwHpnrrD70f31m73gu9t9gvaaK2VsLuG9P4jgeTxWFuwFfLTPcDjlQRTrYI+LX8mH4E/FPL7c3ntzq2p7N7R2tkaTNYTtDubMTb63Hh87RazTZjbuIkioNlbWr6WSQtDNjsXTTxsqt5C6hvc37LtPLfKsZi5Q5YsdsBVlMkaF7llf4g93MZLg6hUMFkRCCVCBTTrkz7w/eh+8F7+Syj3X91d03PbGaoslcW23pmtFs7cRxMOH9sJT2juqK9Wr+1XUDde9+691737r3SE3v2j1n1nj58v2R2JsXr/FUscc1Tk97btwG1aCnilZ1iknrM7kKCniSVo2ClmAYqQPp7V2thfXzBLKylmc+SIzn9ig9UeSOMapHCr8yB/h6IF2H/Oe/lVdWVlVQby+eXxzp6yimEFVT4DfVLvWSKUxGbSRsmLcIbSg9RW4VvSSG49iu19tufL3QYOVbyjCoLoYwRw4yaR+XHpCd220MUF7GXBoQp1H9i1P58OiZZ7/hT3/JzwcBmg+Q+7NxH7p6ZYdt9MdpV87qjOv3arPtmjU0bhbq5IJBHHPsSReyHuLK4U7RGo01q00VPswxz0kbmLaE+K5INf4WFPtqB0ga7/hVl/KDo5YI4t/95ZESsFkloegN9GOlU2/cqDVwUjlOfpGsjcfT6e1X+sR7hUzaW3/OZT/gBp+dOqjmTaWFRcilfMqP8LDp9xf/AAqZ/k85OtpaR+4+0cXHUyeNq/K9EdlU2PpeCddXNFhqiSOPi1wjc+6TexXuJEhcbdA59FnjJ/mQP59b/rJtGoKbmh+wn/BXowewP+FDP8nfsMtFRfNbYW2KsVho0ot/4Dfex5pbIrrVxzbh2tR0BoZCSolMwAZSDbi5Lfe0nuFYAmTlyR1pWsbRyflRWLV+VOlMe9bZICy3NEBpUhlHCvEgD7erAOqPm98N+9Y6J+nPlP8AH3smXI033dHQbQ7c2NmMvJTi+qRsLS5tsvB4yp1rJArJ/aA9hbcOVuZdqLDcdgvIacS8MgH7StP59Kor2zmAMV1G1fRh/n6NBHJHNHHNDIksUqLJFLEyyRyRuoZJI3QlXR1IIIuCD7IiCCQRnpVx6rK+Vf8AKH+E3zI7G3P3B3Ls/fUvae6dr4TaNRvXavae+du1ONxe24ZYMFJiNvRZip2ZTVePSokIaTGSpK0jNKrlifbG67dy/wAw2u3WfM/K23blFaM3hGeI+IqMxZohLE0cvhsxLFQ/xcCOHU2e0n3kPff2Ih3S09ovdDctj269kEs8EPgtDLKqhFldJYpAXCAJUEdoA+fVf2/P+E0PxDzeOEPX/d3yL2Dk1qqSRazJZjYu+cetHCmiqoxjMjsvFT6q2wYy/dakYcC3HsEv7Rez9wT4/IrRUVgptr67jZWJqGBmkuV7eAXRQjjnPWVOwf3q/wB9bY7oT3HP207jCWBZLrabXvAFKM1v9OxrTLV1eh6CnY3/AAme2Ts3u3qDeOY+TGS7M6h2hvODdfY/W+7+sqHGZne1DgZocrtva1DuLbu6abH0OIr8zTRrmDNQzNVUKtDGIzIxF+Wfaf235V5js+btth3Vt3sW8S1inuIbi3WahCzSVt43JhYiWJQaGRV11UZNvdH+9T+8h7s+0vOPtLv+07Da22+W/wBPPf2Uc9vcx27N+tFFGZZYx40f6TPqDKpOnienH/hTZjO/t29EdDbB6p6t7K3J1xR7n3x2F2LvjY+CzW4NubUy22Nrx7f2Nh930W3KSuqcRQVibsyVdFkKqOOipnx4GsOQPY23aG6n2fbWh2R92szv+3ybhaRoksz7bbzG5nKxMQ9wGmjgBgiq0mnSw0tXqIfuM7hyRsXuXz5uXMnuJtvK/Mg5L3Sz2G6vJWtof3vfxC2hC3QBS0ZITIBO5Hh+KGTKU60x9i7yyu28nsvMbBpdy7S3RsjcWD3DtvcOHmjwVZsndO2q+nyFJnaPJRzs8eZxORpkkRRHLJLILuvJPvHy6fmjkb3A5k909z97tjfmxVuxGzpLuN9drcpJEtodtuLcC2jeGQxMtwYo7RKqgwAe+n7u9sffD2N5Q+7ptf3UOYrj24vfokvIkkt9q2q0EBjklu23i1un+ukSRROv0wnlvmo0tPEJ6uj6n/n1fzKOnYIU3B2psLu/AYukkMtH3P13i2ybwwy+cyz7v68n2Nl2eOAFDLUJVsV5N29XvW0/eguZ7qDbuZ/a+wvb2Zo1Vtumns5izUWghY3cDSMxwqRIKnAzTrHH3R/uWPZVrDdt99vfeXfeXLa3immZb8QbhaoqAuWklkEM8cMSAkkOTQVJ6vf+cP8AMa+TOxf5PNF3l2p1JR/Hj5D/ACpn/wBF2yNsbdz2VzE/Xu0t9YjN5c7+ydRlsZicnt7d8/VeDyGQo8ZKhqcbkqqkhnbyxzhMoN2uk5WtbnmDbbCQ7xaw2yxWs7RyeFul3KltbW80semKSK2uZUaeUBUcROgHcpPFr2M9k+Xvdn7xlj7WpzbDuHtxZ3N5d3m5RRvCLzZdpjN1eTWtvIxl1XUUZjgiLMzJJ4ganWjFgmmhrqeuoMPV4vCS4CnjqhVPSCCGmx0Ktg6ijkpqupeWU0lTJHLEQCiqpvwb4fe4u18u7V7d7vyzvnuHtu88/bTv8z2rWq3fjyPdsY92guhcQQ6EhuIY54LireM7SKKqw0/TX7Nb9zfvHvPsnPPLPs7vXL/s/vnJsEV+L97I2sUW3xiXYbuxa1urnxHntLiW1ubUhTCixOx1Kwb6V38oXrKTqb+W18R9sVeGp8Hlcl1ZQ79zlJTvFJ5sz2Vkcjv6tr55oYohLUV7bjEragWXVoJOm/vLKeyO1W+zbF4/iJt23WlqDmg8C2jjcLUmg8QOcGlST59fKd7zc1Jz37y+7vOyyFzuvM243Go/iBupI0PAYEaIowO0DqmP/hTf0507R7d+OnyBTMY3Cd+ZDdFd1Gm2ooh/E+z+rY8fXbkyGTqSjr4x1JnJIZYqqVSgizktMTrmgAjP3k2XbN29r903ndLlILzZriJrKRjUyy3TiOTb1UZb6iNXuRTERtGc0DOT0F/ujvcz3B5Y+8tL7b8t7bNf8kcybdK26xK2lLIWi6oN0JPYDGzC2dSdcySoif2fVAv8snfW5euf5h3wy3NtOiyOUylR3rt/ZdVicUKiStym2exqHJbF3fGKenuaqmxG3c/UZSVXHijjoDK5VYywhP7vN9Pbe5ybekTPa7jtF9BMRwjRIvqY5XwaJHPDGS2OPrg9Zv71zlTZeY/uW857lul5BBfbLudhfWhkbS0s6TrGbaH+KW4ikdFQA14+XX0IflL8wfjt8MuvJOyvkT2VhdhYOZqul29i5mlyO7975ilpmqv7u7E2jj0nz2687MgH7NJC4iDB5mjju4y7trF57e9v5riG22i1UNcXM8iw28CEgBpZXIVak0VBWSQ9saO3b18tHLHK/M3O/MW1cocl8u3u78130gS3tLSJpp5WP8KL8Kj8UjlY04u6jPWvd17/AMKctkZLvTMY/tD437o2T8ZMjNS0e0t9YTLJuvt7bKRqY6jcPZHX2PR8VV4jITMr/aYCtr6/HQ/2a52Kxx7tvvB7NbzvsnLFpzLdWsyuqR7jdxeFttzIxPZgG4s0oKxz3ClJKEypaqK9dD+cv7qD72XKPtbtnuFDtu17rzK0TS3WwWcxfcraJaZidtMF9KoKmWCAqULBUeUjOy91F3L1V35sLB9odMdgbW7M6/3JB58NuvaGWpsxiqrSB5qaWWnYyUORo3OiopahYqmmkBSWNHBUSFfbde7bKkV7BoZ0DoQQySI3wyRyKSksbDKyRsyMMqxHXNeeKe0u7zb722lg3G2lMc0MqPFNDIpo0csUgWSNx5q6q3nSh6Ev2i6p1737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691/9ff49+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3XvfuvdQ8jj6DL4+uxWUoqXJYzJ0dVj8jj66CKqoq+grYXpqyiq6adXhqKWqp5GSSNwVdGIIIPtyKWWCWOeFysyMGUg0IINQQfIg5B6pIiSo8biqMCCPUHB6+br/ADYPg3Wfy+vkjvLrzDYSozHSe98bley/j1LXU4r6eo2e9SFyvXNW8jTmryXVWbqlx7aj9xPiJcfUMTLUPaB+bvbgWfu5yPzHsnMEvL3K/Mu7Rwz3tvM9t+7bt3U3caTKVEKXSn6i11ERIXePKW7t19HX3N/veL7yfc29y+S+eOU7Xm/3d9vNikePbbu3S9/e9lFEy7bdvA6uZmgI+nvPCUSsYtUa6pUBIz8eO3ct8euxOo+4eqs3TV29elt4YHsTBRU9cTLlZsRXNU5zAz0YmSaDDbqw1VWYqWBgFSkrGjP09pN+5o595V9+bv3Y595B3Hadiur82V2j2zpEdvkjFoUa4QeDcXXgKtyZ9ZNxcoZwWr1NVx7OeyXvb9x27+637d+7Oz8xczx7G24WTxXiSXCbssr36yw2bP49tapdyPbw2zRhbS3ZLcqClOvqZdN9sbM736n657n68ycWY2P2jszb2+dr5CKSOQy4jceMpsnSx1HiZ1iraQVBhqIr6oZ43RrMpHvIzcrGTbb+6sZHDGNyAwrpdeKSLXikikOh81YHz6+WCSG6tpZ7S/tmg3CCR4pYm+KKWJjHLG3DujkVkOOIPTT2h39030vmur9tdn9hbd2fuTuvfmN6x6n27kql2zu/d8ZVXelwe3cRSx1FfWGKJNdTUaFpKRCpnljDpd6w2fc90ivprG1Lw20TSSNVVVVUFjliAW0hmCLV2CsVUhWpQEsXVEZioBbSpbSpOkM9AdCau3U1F1ECtSB1ojfz6/hxR/G/5q7g3TiaabCdV/Kr7ruPZNdRAUVJhO0qPIUq9sbax85iSiFb/eSoptxLBpfVHnXWxWJtME+6t1u/IXNmwe9ewbdb3kd5ay7ZusE8bSwTA2/gEXCqwkWO9sW8LxEZHE1tJIjaqV72f3anPnK33hfu/wDNP3QfcXmm527f+Wdxtd02G6gnWG7gjW6F3avaNLWJ5Nu3CNituY5Ea3kVZEKk9Uh1NY2PrHg3HjpM/kKVIptv1WNxtUn8dBcSNRVEMPnxUNbjauFZNUxWKJWSZVQqx9hTaNotuaeVpZ/aLnNuV+Q92k8Dmewu92T6axFq4e1uTraG8vrKeJ3EEQimnNzG9qWfUlc7+YOZLvkHn6Oy+8V7bpz97r8vw/Ucj7rYbBL9XujXsZivbP8ASWew26/tZoojdTtPb26Wk0d4FiCSUNn8cvi18jflvuOHavx36b3h2blhJDDmcliIEpdh7UnlbxTf3s7Iy5x2z8LDRzAh0kqfu3VT4oHaykA7J7R83c0TXk3K9m6cmpM62+5XyfRQzQKxCSxQsWkld0XV4NusxQkBj0KPd379XsV7Acv7efd/mi0Puu1nHJc7FtMv7yuYbpkq9s0sdEjijl/RNxcGJT8ekKR19BD+WH8E8N8Avi7t3queXGZntXdNUd+947wxqM9NuHsbL0dLBVUGKqp4YayXau0MdSwYrFLKFLU1N52RJZ5Qcxdu2vbOXNk2XlXYix2XbodCMw0tNIx1z3MgqaSTyktSp0RiOKpEYPXyt+/XvRzX94b3c5z93ucW07putx+lAGLJaWcVVtLSOpNFhipqoSGmaVwaMALEvb/UQ9e9+691737r3RDPmB/M5+CfwQxlRV/J35Ide7AzkcDzUnXtNkW3V2llm8BngixvXG1Y8vu9/u1sIppaSKmLEXlUc+xXy5yTzRzXIq7Js8ssRNDIeyIetZHomPMAlvl0luLy2tVJmlAIFacTT1p6fPh1q5fKz/hYhhonyu3/AIRfFTLZ0haqmx/aPyPzK7XxRcxtHT5Ci6w2dU5LO1cMcpEiiqy1G0gFnRPc58v/AHdJ3EU/Mu+KgwTFACTxypkcAA09Eb7eghf887dbhkt++TIxRvsODpPzGsH5eXWvR8if59382X5LnIUu5vljuTq7bOQhq6aTZ/x7xWO6ixaUNYqx1FFJnMQtTvWuhaIaAZ8pI+lm55PuY9n9pOQNlMbw7FHNOpBDzkymo/osfD/Yg/l0DrvnndJyRDRAR/qI06SPzZuqlN57r3L2HmavcXZO8d19h7gr5lnrc3v3dOe3llquaNDHHLPWZ+vyMztDGSqcgIvAAHuQLa2trOEQWVqkUC8FRVRR9gUAfbjogk3bd7o1Ny9fUUU/71gmvnUkn16S3mxdCvpSmpUH6SIoadDz9QT4xyfb5cLStPzPSfwb+6OWeRvPJY/5eozbkwyar19KCDb/AIFU/PNibiRvbT3UQA1TIPt6fGx7m1KWclP9K3+brAd04i/FZRkf1aqUn/Y6fp7bF1bmpFwuPSnTg2HcgM20v5KeuabowzEA19IvH4qorX/w1Ff9597F3bk4uY/2j/P1Vth3MVP0sh/2p6lR5jFVXpSpp5xyAFmp5ibfX0CQn/ePbwkUjDKfz6ZbbNwgGpoHX8mH86dZkocY0qVENLTRVSN5UqaeP7Ssjcf20qIPDOjf4hr+7CnAjBx8j1QXu4wdv1UmkeRYsvywajHljHRzuif5g/zu+MctEehPmB8geuqHHRQ01Lt2n7EzW49nCkp5o6iGil2fu2bO7eloo5I+I/AFCll+jEew7u3JHKu+Kx3XYLWYs2osUCuT6610v8jnP5dG9pzZvFoWPjBgfy/YB2A/7U9X0fGH/hWz89erJsdi/kv1d1D8o9sQyUkdfmcNTy9K9ntSRyEVMkNbhYcvsGsq3gfjXiacFkF2BLExJv33e+WL4O+y3k9jPmgJ8aOvkNLEOB/zcP2dCqx5/FVS9iIGBXj9pJUA/YBH9p62XPh1/wAKZ/5ZHylkw22t8b/zPxO7MyngpztL5C0dPgNsT5KerFJHSYXtbGT12wa6OQyIyvWVOOcq3MakEe4R5j9lOdtiMklraLf2a51QVLUpXMRo9fkof7ehnY8xbXfqGinAP+D7afDXy1afs62AMFnsHujD47cO2czitxYDMUsVfiM5gsjSZfD5ShnGqCsx2Tx81RRV1JMvKyROyMPofcTSwywSPDPEyTKaFWBBB9CDkH5Ho8BDAMpqp6dvbfW+iCfJr+WB8G/lqtbW9u9B7TG76uKdE7J2LHL152PTTz+Zvu23XtF8XW5aVJpzII8iK2mdwC8T2A933H6TfLT938x7Xabnt/8ABdRLNpxT9OQjxoscDDJGRmhyepJ9tveT3Z9ndwi3P2s9x942G5Vq6bS4ZYW9dds+u2kr564WJoKmnVZnTX/Cc7499SfKHZ3cdf2zu/tHprYeRj3bgOj+wtu4Stq6re+Kqo6jasm6N7YibE0m5tobcqYkrf4fNh1lra2GL7ieSASQSgzl3209ueUuYRzhy7sdxDvsaMsMbzeLa28jihuIVkUzCZASIdcsghYiVWMiIVyq92f7yH7zXvT7LX3slzvu23/uu8kQXe4WkT2t7d2sYA+imCOYTHMwD3EqKjSisehVNejM/wA+/q9Ox/5ZfdeTVaX73qbM9f8Ab1LNUUzVDRU2094Yun3CKfR6oZKjaeXr4mflRG7agRf2f7/YjdeTuetoAcyz7NctHp+LxrZPq4SPPV4tuumma0pTqIPuc86x+333pvYnma40/QDmCC1n1fCbe/DWUiuODIfHGpTUECpBp188XDQtVYTdVFRs0lB99lcbicXHURfd4uCCFqOpo0qZiphaoqA8tNBKdNPE0ahtJFsavc+72e55s9mL3nCAR7vd7Xtl5ve5LEyRbkt1JHOtxHBH2zS21pS3vLmGjXd0srOgkUk/TP7GbTzNa+233n9j9vLwXHLNlvG87Xy3sT3SyT7Q9nFLayW8t1KfEtoby91XVlZzVWxsXgVJGjdQv0f/AIXfzMf5fPaHSO29v9Z/IHbO3U6Z6qwNHuHZPaksnXW/9r7Z2LtiChqK/I4Hc4onzFJQY7EM8tXipMhSELdZTce8yYrE85XV1vHJN1a7xtVzcOUksJBMqa2LBZIxSa20g5FzFCVAqcZ6+Tz3I9r/AHT9mt2Gwe8fIe67BzASBS7gYRzyMQP8XuE1wXJkZv01hkd3qKJXHWkl/MR+bW5fn58oN294V4rMf19jYp9jdD7VrI2ppds9S43Iz1GOrq+kcloN0b+rS2Yyur9yJpoaM3SjjthZ74c+2vNHMMfL2w3ok5L2RpEikU9l1dkBbu+xhkJUQWxz/i8auKPI9fqB/u2Pumn7uXsxBzJzbtfh+8PN0cV1fhgpks7Q91ntqmlV8NSJbha0Nw7VA006vg/4ThfBkVMm6fn12HiGCf7nurvjjTZCkZSKVJDju0e06LzILnJVkT7cxk6crT0+TILR1KH3MXsxyg3KfJzb/uEGnmPmCNJADTVBtqsHt4qUqrXbgXUlDmJbY8GYdcr/AO9k+9APdb3XtfYnlLchJyFyZOTdtGey73pl0y1IoHSwjbwkrqXxnkZSGjHQE/8ACm2pqJvln8YaSeRZqPGfHreNXQQMEJo6vLdixQ5KeFj64zXw4elV/oGFOv8AT2H/ALx+huRuQoFchpN5vi61Olglra+GWWtCULPpJBI1sBgnqXv7kKzgPPP3hN0ltI2mh2ra0SQqpdA092XVGpqUOACwBAbSteA61koNtUeSzO5KXItWUW64p/4jgsqs8locM6RRY+XHoXEDU1JVK0dXEVtIzEuSHUgubnjd+V/b32u3ble2s7/2cltfod42p4YiJt1Vnkv4twcr4wubq3ZLja7xZB4axqsOkxSKc6l9tti9wfeL312Dnfc9y2v7x0N8d25b31LmYPb7E4ji2yXakEgg+jsblHtN629ov1nkdrkulxE4Nb8Vflj8m/hrumDs34/7/wAn1nna6qjG9Nn1CNnOs9+1FEHpXg33sWoqIsfnKaeK/wBrXxPTZamjK+GqiI5ILD3Ru/aTmXduVeUt3j5m9ozKJbW2uy9BBMFmAgmWkljfQBjDceFWB5lYyRSqadU9yvuc+2/31vbfYOYvejkl+TfvIR2729zuW3okc31VtK0LySRmsd/t1yUFzbLcVkEMiBZEZet0n+W3/PA6W+bOd210h2dtuq6O+UebhqosTs1TX7i697PnxGIny2Zr+s93QUrS0r0tDj6mqmxOZSkrqaniZo5KtFab3kdytzNyh7hbde7pyPubtLaxCS6sbkCO9tF1BNbUpFcwBmRRPAa1dRLDCSAfn5+899zf3s+6dvMEHuLtUN3ybdzmOy3izJayuWNSsTqx8a1uSoJMMoIIFUkYEdXlezDrFfr3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de6/9Df49+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691Wt/NU+COO+e/wAVtx9fYmHHUfc2xJpew+h9yVqwRLQb+xVHPG22K+veN5aXbPYWKeXEZEqdMS1EVVpaSlism3PZdq5r2PeOUN+bTtG4RhTJQsbeZam3ulUEVaCQ1YDLwtNEP7Q9TN93v3y5o+7h7wcme8PKmuS52uelzbgkLe2EtFvLRgOJliGqLhpnSJtQAPXzX8/G2297+PduGrdq1uCizGGqqXI4qemyOK3nSZGfD7m27uGOGB6qhzOHaieA00tgZhMLl0A9wTsvKPPVz7Uc/wDtjtE8l5z6nMcEO7bdLeKr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q3AZ3a+YlMMceN39tSpghavpOVanqYZomcGQRjX7yft9yryvuewc++3quvt7vNhZTyW2hgds3G4s4p5bUVrqtZwXms3JzSaI0MJrC/3BPvJ7l7r3nuX7Fe6m5hvfDkTe9wsvGdlLbztUF5JDa7kKU/XiWltdx0DArHORpmWm1p/wnE+Dse2dj7o+eO/8SP7x9oUuR686Fgr6aJpML1bisp49377oDIHeGr7J3PjVpYZV0scTiI3Q+KtcNJPtHyb/AFL5IhuL620cz74Uu7gkUeK1I1WdtxxqRvqpRQajJAG7oeuRn96X95tve731b255X3Mye2vJLSWiaGrFdbo1Be3WCUcQ0FpEwOCs4IBPW0p7kXrmL1737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvdf/9Hf49+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Wll/woV+Ag6g7VpPnF1nimi657vzeO213njaOK1JtPuKWmSk25vsJHpWkxPaNBRLRVzWCLn6aGQlpso1oU+8ByP/WjltOetutVbfNot1hvaL3S2FQkFwaZaSydlikNCTavEMJbseu3P90B97BuVOa7r7rnO+6Ecvb1NJdbE8hxBf0Ml1YBmIol2oa4t0FT46zKoAdR1q+R5fMYbCybcjws5r6OsrnostPTxjb7UtXWTVEOXr8iahY4Eo4KgmWn5nkkTSoIYEBzc9m9vvcfnja/cy854sxype2Vn9Xt0TyHfPq4LaO3farOzWJnlkup4lW1ulIt0hl8SV1ZCp6J8vcwe7fsd7Z8w+y+1e2u4rz/ALZf7ithvdwsS8sDb7q+mvI99v7+SZY4IrG1mZ7yykBumuITFCjiVXG0r/Kp/kT5ruGLa/yL+cGBym2erHahzuwPjxkIqrC7o7KpgI6yh3J23GslPk9pbLqnCSU+3gY8jkojev8At6cmlqBv7dez9ryTfQ8z832sc3O0T67a11LLBthB1KZWAK3V7HigzDA6gt4soKw8xfvz/wB5xu3uNbbn7L/d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bd22zfd6jk572JnvzeSvHCn7qJ1yyyEBUjj2uYV7RRIJ1WNCsSr0Ef7zb7kex+0XM/tjzj7BcjPHyJzEYNjbbbFHlaPeBqW00KCWL7jFqVpHYkzRBmZASRr09l1my49wbw3d11jch17gn3FuGu682DnM7TZncuE65r8/W1O0dkbsqKcRxZyrxuFmipDNCupagFopX9TSRnsd1ac/e4fMHJvL/JF5uv3ft+3iVlnktHjSxu/p/wDGd1226posCjq07W8sjxmzCQ3UdQGTo1e7XvvtF7F+3XPfuH7s7Ztn3y+UOVrOO5S3vI3G72q3C/S7Luu3FjJuSzB/pormKJJo75mms5QCyybdH8q74udQfzH/AOTplvi52tWZzDzdZfJLsCLAbzwlRFPvLrnOT5rFdk0GV2ZV5OOopsfFk9sb9qsRNCFankoquoTTqIKzPylf7ZzD7W+3Kb5t0W58uT7MlpcQNqjiuDt13NDEWMZDhkMEEquCH/CToZlPGT73e/8APH3fPv7+8fOPtzuM/L/OJvVv4JE7nij3jboTcRsDRXVy86MmUVlRh3RqRtI7M2btfrvaG19hbIwlBtrZ2y8BiNrbV29i4vBjsJt7A0EGMxGKooiWKU1DQ0yRpclrLySbn2a3V1Pe3E13dSF7iRizH1J+QoAPQAAAYAAHWBzFneSSR2aV2LMzElmZiWZmJyzMxLMxyzEkkk9Kb2x1rr3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de6//9Lf49+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3QR99dJ7B+R/TXZPRfaGL/jGw+0dp5TaW4aVSq1UEGRhIpcti53V/ss3gsgkNdQVKjXTVlPFKvqQe1FrcLbTCSS3SaAqySRuAySxSKUlicHBSSNmRh5qx6W7bue6bHue275se4SWm92VxHcW08ZIeGeF1khlUgjKSKrU4NTS1QSOqK/5af8hTZ/xd3q/dPyr3Btbvrtbau48j/oiwOLx9V/oy2bjcbXyxbf7Dy+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atpnwCDxr86Yz5EYbhhqqNpX3BnQm697917ok/zS/l9fGL57bRxu3O/tkNkM9tinyidedmbdrDg+yOtavMLTjIVu0NwLFURRx132cQqqKsgq8dWIgWeCQAAbu1td02a85a3uyjveWrmRXltpdXhu6BlSQFCrxyxh20SRsrrqIrpJBHftn7nc++zXOu1+4vthzJLtPOdmrLFcIqP2PiSKSORWSSGVarIhGVJCspow0wfnn/JX+VXwsjym+dr0tV8jug6N6mrfsbYe36kb22TjIS8kcnaHW9I9dW09NDAt5svhzW40WMlRHQoVT3jXzX93u4s0udx9tJ5b+xyz7fMVF9GAtWNs40x3ygAgIFiucDTE9C5+gn7rv97fyF7jDbOSvvIWkHLHOb0jTdYtR2i6bCr49avt8sjZIcvb6mAWUUIFOM258h5lmhwUG4sbLBT1OErMXVUV48gmoOKuSrnjhjglJDxTxagikqRe1465f5S5A3rYoYr/ANyE5c5ptrmaHcYdwtrt0ktyR4T2QtImkeZBqjuLG60CSQI6vpJ05584c3e7HK/M92/Lns23O3t1eWlvcbPc7Vd2CyR3YVlli3J72dI1hdistpuNmJDHE0iPHrALKfqPpvsTt/e2P2N1n1tn+3O39yVc2Yg2vsbbz7jzsGr9pJIqgxouE29h6eMRHIV89JRREM8kseoj2Nr7dOdfc+7t+SPaCTd4PbDadvi26KOS4a1tTCCzTXu66JBapcX0zPNLEC76NEA8Tw8w9d3XsP8AdT5Z3L3m+9xfcr/69W+bxLvEsgt4r2+juGVUtNt2XxI2vpoNtt4ktrdwEQyrJOBGZCBvpfySvgR8gvgf0l2liPkFuDav8c7h3xgt/wCO612pWPnYutHodrUu3MnSZrdaxU+Ozefzi4+meoShWShpft1SKeo1NIciOT+XjyXyNy9yXJvQ3CeykuJGlWMxxKbgo5hh10kdI3Vz4sixs7OQI1ULX50/vo/eG2L70Xv9zB7uct8pzbRs09la2kUc7q1zKlorqJ5whMcbSayVjVm0IFDsX1Uur9nXWKvXvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3X/09/j37r3Xvfu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tXK0Fdtvb+7soum2eoaVKnUC1RFVkrpJeZ+VOTueZ7a8515eW93KGmm4WRoJ5AKUiuZY+64hoKEPSYDEU8S4OVXsP99T7yH3b9i3flb2u9wHj5XuoXRLO8jF7bWcj/8AEiyjlb/FpR5IjfTkDMBOerFPjB8PPjl8ONjR7B+PPV+A2HjJI6f+OZqGJ8lvPeNZTxhBld67zyb1W5N05J21MHq6iRItRWJY0soEAlWKxttpsbaG12WCvhW0CCKCOtalY1wWNe6RtUj8XdjnrHrnDnLm/wBw+ZNw5x5+5ovt65sumJlu7yVppmqa6VJ7Y4wQNMMSpEv4UHRmPbPQb697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r/1N/j37r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3XvfuvdF8+VHyg6Z+GnQfZHyS793XT7Q6v6wwM2azmQfRLkclVMyUuG2xtzHtLFJmN1boy88NDjaNGDVFXOi3VdTKbbFse48x7rZ7NtUBkvZ2oPRR+J2OaKoqzHyA8zjpuWVIY2kkPaP5/IfPr5Mv8y/+Yv3N/M/+TOd+QHbUlZt/ZOHbJYDofp379qrCdPdcT1Ebw46MIsVNXbz3IlNFU5/KeNZa6rAiTx0sFPBFn9yPyZYcjbHDtlkiteNRppad0r+p44WpCLXSi+pLM0J8zcxS7pcNb2z/AKAPl55/mB5ep7j+GhcfjR8bOxvlp2fD13sNVxGGxMdNlewt+1kLS4Lr3a0k3jbIVYuq12fyADR46gU+Som59Mau6j3bNru95vBY2NRnvk46R6ehc50itMFmooPUDe9PvNyd937keTnLmytxuNwWi2+xQ0n3C6AqI0/ggjNGuJyNMa+rlVO1N1J1H1n8cuucb1V1FhjiNtUDLU5PJ1Xjl3HvLPMgWr3PuzIIofIZWsYEql/FSxkRxqqge552fZ7PYrOOzs4wGHxNxJJ4mpya+ZOT8gABwc9w/cTnf3n5yvefPcHc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rKbEW9udrhgVqDxr0U3+3xXEbKVqpz+YyCDxBByCMg5GeqSf5h38vSmxtNuD5L/GvAGHHwtNmu4On8FSjx4uIjyV/YfX1BDylEpvJlMYi2jBM0QChgIm5u5SNm028bRFWE5ljX9pdQPPzZRxFWUVqOun33PvvfzbjLtHsl71bsGvWAh2nd52zKeCbfuEjcX/AA21yxq2I3qSCaVaStapWirsfX1FDkKOopcpispi6uairaGuopkqaHJ4yup2jqqKso6mJZIpY2WSGVQRYj3HREcsRDqJLaRcg5BB66Yq11s974iVV0ahB8vkR/qqOB8+vpI/8J1v53NT86tjD4ifKfdFGfmR1NgBNtvdmSnhpaj5Kda4iApJuqGM6En7R2dSRKu46aO71sBXKRBlatFNhf7we2f9Vbw77skJPL87VZQMQOT8P/NNiez+FuwgAx6ps5f32Hd7aPNJ6ZFfP0/ZkHzHzBA2k/cH9CLr3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de6//9Xf49+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691jmmhp4ZaioljgggjeaeeZ1ihhhiUvJLLI5VI440UlmJAAFz72ASQFFSevcMnh18uv/AIUF/wA3Ct/mQfJiXp3p/cjz/DD427iyeN2IcdNKmN7n7OoWnxG5e5sgFZIshgaF1mxu1VcOsdB565Sj17xpnB7Qe3w5P2f97blDTmG7UagaViStViHnXg0nCr0FD4asYt505grq2+1fHBiDxqOH5g1P9E0/EaUZ9T9V76+QPZ21OnesqEVu6t2VbqlVUK4xe38PSL5M1u3PzgFaPCYKjDSMW/zrhY1uzBTNltaXN9dwWNktbmQ0+SL+JjSpoPIDJNAOPUIc989cre0nI+/+4/O134Ww7fGCVWniTzPiG0gXi8870UAfCKuaKpI2zOi+juvfi51Rhuout4BNTUR/iO7d2VECRZzsHd80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PbryexO1eq904reex924aYpX4LcGHnWemmKWaKvxlXHqp6ylmWSmraKaSGVHjdlIC3Db7PdrC72rcIVksp0KkEVBBwR6j7RQg0IIIBGf+038+z3yuhOiv7R6fI+Y+YocEg/Wo/lF/wAy7YX80X4i7X7xwsGP2z2rtuaLY3yA6xpq6OpqNhdn42jieukpImkarbZ28KYjJ4OocMJKOYwM71FNUBefvP8AyZdckcwXO2SamsWJaCQj44ycA/00+F+HkwGll6nfb72K/tYriJwQQK/6v8nEcDkHq0X2COlvXvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvdf/1t/j37r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Wp3/AMKlP5pVd8Xvj5ivg90lumXE99/KjAZCXsXL4Ws8Ob63+ODyVOF3DLFLEDLj8321kUmwdE4OpcfDknGhxA/uePY3kYcwby/MO4Q6tssmGgMKq8+CPkRECHp/EUNCAw6DvMe6rtti+kjxmwB9vr8sEn+iD506+chMRjqSOlggld28EUdJSRNJPK8jJBQ46kiTVJJNPIyxoouWYge8zGZVXWq9o7VA8/LA+fADqFogb25aeWVRGCSXc0UAVZ5HJwFABYk8AOtpn4BfE2L4o9Ptm930UP8Ap27ZoaHMb/qWVHn2dtyWNKvb/WdFKF1QjHxOtRk9JPmrW0MSsS+5o5M5eG0WhvbtP92M9K1GVA4KK5ov5VbUaEaT1wp+9v8AeAk9+/cNdp5cuW/1quX5ZIbBRULeXAJSfcnFc6yDHbV+CEagAXPRv6moaRyT+fp/h9ef6exgx8h1jnDEI1AAz1D916f697917r3v3Xuve9de65KL/wCt+famGEyHHDrXQm9AdA9+/LnsnPdWfG3a+3Kx9jfw8dudxdj1mVx3T/UU+WpFyGL2zVDBQy7g7C7QyWNkSqTAY5oI6KllimyFXSpLCJMePev7yHL3tFejljbNvG586mJJGh16IbZHPY9w4BNXAJSJRqdatVVAJzo+639x/mr7wW1f195l3xtg9rfGeKGdYxLebhJH/aCzichFhjJ0vcSdpbtQEkE2l9dfycvkx0T2ljO8B2r8fflRNiJdsvP0nu/rvdXSOIrMds+qq9x4jEYDfmO3d2gsKy7+kpM5V0+SxMtLk6zE0EdQ6QQaW55+6fu1zJ7x7vtW580x28CWUTJDBb6/BUuQXlIclmkYALU4CigA67Jewn3fuQvu4ct77y5yC93O+53KzXV1dlWuZvDBWKMlAFSKMGoRRQtRjUivRL/5qP8ALr/nIfzOvnf8ee0ekEj+CnWvSfRO9Otanfe7u7tr7l/u/ne3m3Rhe4K/Y2J6uOX3Dm33311X4/DVLyQ0AmgpfHJLBpW8cMqIFKzAg8cGv7P9nqaAzMWDRkU4f8X0djZm3cL8Ht5/yofgLvzp3b/V+N6f7xG3+gt6bOytfuDpzviDJdIdo4nc+5V3BuXHY/K7R+QFJu7OSZbJ7dyYkmyC5CerxdbWKskULyQCZJ2gkBohYqcMAuTjzA8yOHn02XZGjWRM1GRkVOPyz1TR/wAK3vm33Z0V3xtf45bj2vB2D8We/vg3vzA7a2Nk9y7o2ztvCd85vsd6STvepg2tXUMe9969T4fB4+LDYvMfcYml/iUlQYfLIH9pgdMYI/FUH+X+fq5UvJQ8FoR/P+fWw/8ADP42bl+WHxS/kg/IjvCrOJ3t8Vuodn9wV2Flppv4tuLdu6Pja3WO26iWtEpFNAmPzwylYH1mplWMcckMyRkOBXh/q/4vp2Nhowajq738/Tj+vvfW+q8f5cuSlzGxPkrncioiy2X+cfyqkyhdrNJPjOwXwFCxB0otsLiKVVVfSEUfm/tyRaaKD8I6TQzI3ikuBRyP2U6IV/wpq+RtJ0T/AChvkxgcR2FtHaXY3d+I271Js3buX3JSYrdu+8LuzeW28V2RiNhYb7qLKbiyUWwqyuNVHTxyLFRPI0lgRdlvIfPpSrKcgg4/1H/V59a6X/Cajs/5h/GXcXafc3yN+Hvzr3h17lfjh0/0J0lg+jvhxVnCbj2n1tu/dmYp907gzIbr/H53cO2oszLSRZCsFflspT5Bgah46aNPe1ShJ9fP/J1XxQ1FDA062Y969l9qZX5GbiqelNu7t6S7G+fWxOkdi7Ey3ZGDgwHYnWG0eoqHe+c+QfdW7up89JJV47NdP7R3HTYXBJXx/Y5LdOUo4w9RSq4f1/d7ZsO2XW/b5dpDtluKu7Ht4FgCfkAWale0V6YE7XMyWNqKzGpr6AGhNPt7R5Vr6Ho5fXGxuiPhx1LhOj/jrsjAdebE28tQTR4SgpKev3Fm62SWtzO6t05Kkggm3BuvcGSmlqq6tqC0s88rMSBpUcYvvk/fzS2tb/l7la/eGycsipGSJJz6yafhQ4IQdo/EWOepo5L9vJ7x45biL0Of9n/D1W/82/mrjepNqVeIba9F25vzdu1t8bg291PlazHw7YrNnbHxEmU3tvfsrKZaiymO2z1ltuneOCpqpKeaatramGjpY5JpfTyR9u/b/nH3953PNO98wXG2bJbX9rA97GJXmjub2UR2lnt8SOjz7hcNV0RXURxI88rLGmcjLTl/btnWKySBfrWieRuKaI4l1ySO4+FEWhJNcsihWLCmu31htvsOPML2LkE6z6y2L2TtOh3NkvjP1jgN0DZHWm980Ey8WR6/zu6dxZSpwlFPQ1YjyeNpaemxk8/7sEEDag36IH3Ofu8e6/3cPbDYOR+e/vAbzzxtMNhGsZ3eGI3tpIFUmBLyKQtNBES0aiZSRpqrZOr5C/vxfeR9mvvGc+7ju/InsLbctc22G4z28u8WtzpXereORk8S+25YUgS4qtYp4dDFf7VWLE9DHJ9R/sT/ALf3lQ/E/b1hAOA+zrH7r1brmjaSLnj/AHr/AB9+Boa9aIqCOneSjwe5cJm9o7sxVJuHam6cRW4Dc2ByESy0OYwuShNPW0c8bAr64nujD1RyBWWxF/epoIbqGS3uEDQuCKHPHGf20PyJHSCO53TY902vmHYL+Sz36wuEntp4zR4ZozqR1I9DhhwZSVOD1qe/Lv4zZn4jd25Lr+R6rIde7ghm3J1Huao1P/HNlTz2OJrZioR9wbRnb7WqQEsyqklgrj3j/vWzS7FuElhJU2x7om+X8JP8SnHAVXS3n136+75717b94X2wsucI1SHm20ZbfdrZafoXqivioOIt7tf1YjwBLJkqejm/yYP5kWY/lg/NraPaWUyFe3x47XbF9Y/Jbb1K0stM+xa/IKuF7GioVkEdRuDqjK1ZyEDhWnkxslbSIVFQx9xR7m8mJzxy1ParRd2tg0kLH+MDKE0wJANJyBWjNXQvWTPJ++Na3AtJidLcB8/MAfPiP6QIGXPX1s8VlcZncXjc3ha+jyuHzFBR5XE5TH1EVZj8ljMhTx1dBkKGrgZ4KqjrKWZJIpEYo6MCCQffP90eJ3jkQrIpIIOCCMEEeRB49TECCAQcdT/det9e9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvdf/9ff49+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3XvfuvdBr3L25sPoPqbsnu3tHOU+2+uup9k7l7A3pm6lkCY/bm1cTVZjJyxI7x/cVj01IyU8KnyTzskaAuygrNu2+73W/s9tsYtd3PIqIPVmNB9gzUngBUnqrusaM7HtAqevjf/ADM+WfYHzq+VHdvy77PaeHN9t7uqMtg9vy1D1NNsrYOMiTD9c7Bx2uR0Wk2ltKlpad2QL56rzTuDJI7Ho1yty7acrbDtuw2Sj9KMBmAoWbiznANWYs1DWlSowB1BvNG5tue5PFGe0EqP8p/kB8woPn0aj+VV8ZKbtztfKd+75xkdd1z0bX0423Q19OJqDdnb1TH9xi00u3iqaLYtGRWyqVI+5eEH8j3J3JmzHddz+vmQ/Q2xx6M/r/tBShBPcwqKDrn99/H3um9u/b+y9qOV74w8580wt9Q6NSS12lTplOMq96/6KEGvhCQ+nWwxla+WrqJZJZDI8kjySyMbtJIzFnc/4sxv7mpjSlBQeQ9B1x72+0SCJAigKoAA9ABgfkOmMm5v7b6M+uvfuvde9+691737r3Xvexx610w7y3I2ytl7p3bDSrXVuAwtZW4rHORpyeekVaTb2L5FichnKmnhA/Oq3tNzHzRtPIvJ3NfO++zLHs+z7bc3s7E0AitYXnfNRQlUIXPxEdC/275J3L3M9w+R/bnaFY7hvm621mmkEsPHlVXYUzVULEeh62ZfhPjeufh78e+s/jli957Pl7FocY26O1JDufbC7s3v3JvELuHsjdeWo48gtfW1+Rz1XIsJZWMVDDBCh8USAfnwe5n9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vjJYeIvEenqP28B5KVr1te+4G6EnXvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3X//Q3+Pfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3WnL/wAK7PnNP158f+pvgJsnI1FPuj5J5OPsrt2SkqZYDR9KdcZmnkw2ArRC8bSwb87GggYi5XwYOZHUrKPeRH3fuVV3DeL3mi7jBtrMeHGD5yuO48CDpjNCMf2lRkdBXmzcxt+2vpekj4HrXyp8xlvnpp18/mLHZfNZLCbV21RyZLcO4stjNvYDHRLqlr89nKyPH4ymCj8vUzhm/GkE+8vlWSVlSNKzyOFUfM4A/b1CLXm37bZ7pv8AvVwIdns7eW4nkPCOCBDJIx+QVaD59biPSXTeF+NfSHX3SOD8Mj7Nwy/3lyMShWzu+cqRX7vzU7L/AJ15stK8MZN7QQoBwPeQOwbZHtG02lkhq2kFj6k5J/MkkVyK0PDr50fdL3I3L3q90Ob/AHO3QMqblc/4tGeEFjF2WkKjyAiAZgPxsx49LBxqP5ve5/PP+J49nKxtIcDHQcwqj064eJv99/yP2o+jl46eva19evGI2/40f+N+2Xt5VNCnW9Q9esZBHtkoRxHVuuveqHrXXNUNx/sOP9t9fwPbiRs3wivXiaCp6bNy7S25vnbmW2hvDEw57bGehigzGHqJ6umhroqaqgrqdWqKCopK2EwVlNHIrRSIwZRz7e3DlnbOadnv+XuYNsju9ju00TQyCqSJUHS48wSBUHBGCCOjflnm3mTkbmXZ+ceTd6m27mnbphLa3UJAlgloVEkZYMAwBIBINOIoaHplHQfU1VS+Fentn1FOTq8q7X+4qjKV0NOcpZsk1Uy/WUzeQnm/tJH7Xe1Nts6cu/633LqbKooLc7fYCEAf8KMHh/8AGehdL94f3sG8Pvtx73cx/vtqkytucwc1NaGslNNfw6afLoVOu/8ATx0y0T9Cd2dsddUMPgWLYG8p8l3N05Vp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G83lVniimqNtpNDmaRZGWNazGxMxAB9xLz/yx/WzlLddmC1uiuuI0rSVDVafacE/ws3WdHJ+5NYbgbeRuxv8I4j8xX7WCjr7CWPyFDlqCiymLrKXI43JUlNX47IUU8VVRV1DWQpUUlZSVMLPDUUtTTyK8boSrowIJB987nR43eORSrqSCDxBGCD8x1NwIIBBx1L91631737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvdf/0d/j37r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3XvfuvddEhQWYgKoJJJAAA5JJPAAHv2eAGevdfIR/nC/LeX5t/zKPlP3lTZF8hsfFb2n6b6lJXRT0/V/UDz7TxNVRxlmeKPcuZpK/MSKSbzV7EcEe+hntpy+vLPJWy2BSly8fiycamWTuYEED4ahBjgoOeoT513E3m5LbI1Y0FfzPD5EaaMD/SPXH+Uz0zF2T8lcp21mqNKnbPx/wQ3BRpURF6eo7F3Os+O2hGCR42qMPRpPWgfVHRWFiPczclbZ+8N78aRK21qta/0zWn2ELqI+dOuf8A9/z3Ibkv2TseQNuuSm983XRt20mjLt9tpkuz6hZXKQk8CGYcD1sTZCoaaofU5a5JctySxJJJP1JJ5J9zio8Rx8+uONpEscK0UD0+z7Og/wAnl9+ZfsHYnR3R3Wdb3R8gO0aTM5jaewoc1TbV2xt7Z223p4ty9ndqb4rYaql2b1/gqutgptaQ1Fdka2eOlo4ZJmA94u/fH++p7KfcW9q5fc/3i3Rkt3fw7a2iGq4upmFUihjAJZzx4aVUM7UjSWSPL/7pX3QPcD73HNO87by5uUG1cm7QiNuG5zqzpEZK+FbwRL3TXMgBIFQka0ZyahSbNv5aX80iHHfxkbn+BlbkHpmnGwFqe9KGGGpMWpMcvYJwVTNUqk3pM5xSXHOj8e+CEH/M0x7VnfJLab7t++rsGuizC4tvG01+Mw+NorTOkH5VHHrqrL/cz+052xYIPfDmJd4CCszW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OMumVwSG/wA2pW44P62tzYMOB+fae4YxqRmv8/sHRvt1l4zpIwqeI9KebN8ul/i8aXkU2IC/2oz62vwHNxaxt/tvYbvZzFqqf1Wp9lOhlZQKwEQBMQz8yf8ALX+XQ87AhSmroDVU6tRGYLVUhFkqaedDDVRuv6RHUUsjow+gDE+wtdsZY5og4qVND6N5H0NDQ0+XQmj2lnh8UArLxU4wRQqQONVYA9aPXzF6Sl+NXy8+QHSv2z0uI2z2JlMltOMxeGN9k7yYbn2q9Otz/k0WPySxqb/ROefcdRkFpQDgHUPWh9fnxFOu23t1zV/X72w5H5vdw17c7eiTmtf8Zt/0pq/Mlan7etmz/hH98jKnZfy3+THxayOTq1wHdnUuG7Z21ifGZaFd89UZcYXN1EblgtFPXbR3YplsCZ/s01f5sWx5+8Rspudi2ffo1X/FpzExzq0yjHyIDIPsLH16nvkG/wBdu9m7VYEgcMAdw+ZJ1N+S+XX0LPeIfUj9e9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3X/09/j37r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvdaif/Cwnuqr2n8Kvjd0RQVNXTP3n8jEz+YWJITR1+2emNrVueqsdWyOplUnc+5cRURKhGpqY6uBb3kF93fbY7nmfdtxkVSLe00rXiGlcUI9O1HH59BPnK5e32eYISNSsD8wRop/vTqfy6+eU+HrdzZHCbUxwZshunM4rblEqqXb7rP5GmxUTBBdm0fclj/gPeYboZP0krrdgop8zTh+fUKR7hbbLablv96aWdjbS3D+XbBG0pFfnpp1usR7eodj7a2rsXFRxwYzZO1dvbQoIIiGijg29iaTGEIwtdWlp2YG3595JWkAtLK0gBBCRgYFMUAGPLFOvmem3i65o33fuab9y97ud/cXbk8S1xK8ufsDAfl0zhjrt/vv9b28jUavn0YEVBHQS984LfMuz8H2p09de9/jpuug7w6dKEqcvl9rQTpu3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1UnI/I/sHWV/3Z5vpOdN82xidF7tbVAwNULh1/ZU+RPWsXtOrrdnV22t44VEhz2zNybY3lhywZlGW2pnMfnsdVzgNq9FVjkJsQ1h+D7E8kSXSTWs4rbTIyEeWlwVI/n1mI0j288M8PZMuQa+f8R+dOPnTHX2V9hbkj3lsXZe74nili3XtPbm5I5IFdIJI85h6PKI8KSXkSJ1qrqG5A+vPvlte25tLy7tSCDFKyZ49rEZ+eOskonEsUUgNQyg/tFelZ7TdOde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691/9Xf49+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xy4/8AhTtvLLbr/nGd44jJ09LT03XPVXQmzME0CzCepxNbsKHfMlRXGVipqDlt3VITxhU8ITgtcnOz2Lt4oPbrbZIyayzTu3A9wkKYpw7UXBzXqH/cBm/eEINaU/kFQ4/NjX8uiM/yksOuT+a8eVkijki2p0/2blQztpanra6mocTQzxJ9ZW1VDAj6BefeQXJkUsnMlnJEw0xoS3qVYqMfzH59c/v7wLcmsvuytYJIVe/5j22LAqGRGeV1J8hRRTzJoOtjTKH99uBxf/X4/wAfc4PxP29carAARDOemb230YdZoWII/wACP979uxnuB6pIKqegS+WGxm3h0jlt3YjcdDsfsPoGr/0/9Vb/AMjJ4KLa27+uqWbKzwZWYAn+7268LDPjK+IhlkjqFJVioHuHvvMe0vLnvL7Mc18scyCJIhavIkr0AjZEdgxYg6VC6gzfgB8QAtGvWSv3JPf3nH7tv3nfbXnzk6Ge4kutwg2+5tYhqe5hupVRQq1Gp4pCsiioqgkQsFcnqxf4B7F3jjuucn8pu5cFS7c+QvywwW1Nw5ratO0ktL050vjaRa7rDprBPVRpU00Tiqkz+ZDKks+SrlWUfsL7+SLmjc9sFzb8k8uXrTcrbPLIqzkaTeXTGk92wBIIwIockCNag9x6+1DdzvPMl/cc38yWYg3u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HGouL2/i0/bpcfEGN5ZHJ+lH2p9ruVPYz292bkHlO30WNtHRmNNckh/tJJD5u7CrZovAEnU7/KX7ze9HPX3n/dne/dnnwiOaf9O0tVP6djaKf04EpguRmRh8TYACqADU4mjLMjaSlmKqT9Av01DUb6rm3PtVvO4qC0evNPL/AAf8V0l2uwUJGVjoPIHy9Seiu/zZdlLun+V/8mo5YTVSbXo9hb9juzRFJNr7yxkyTuF/zixGrvp4v7Dew3Q/rRYOxoGLKB/plIp/n6nb2Ziaw5/5cmX8fiRnFCS6Ng/KgwetOTC4lp8FXEoryVFHVXJuos9K+pblXIVGa9xa3+v7lqP+3SpoAw/ZXrMudAzTEgef+r5/b19YL+XTnYtyfAr4c5iA1Bjn+NvT1PernFTUM+N2NhsZK0s4eTyFpaNiCWLWtfm/vmxz/CYOeebYjTG4TnGBmRiP5HqedjYPs21soIHgJx/0oHRzfYR6NOve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de6//9bf49+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xygf8AhQxVzVf85f5pGaeaoMGT6lpUeeV5WjhpuoNnRQ00ZckpBTRqFRB6UHA959ezqLH7c8v6UC1SQmmKnxZMn7fXqFeeWL7mdTE0ZgPkNMfQZ/yaqFan5LdwZFj+5iui6oRfT65LduLpZD/X9HvIL2+CNv8Acqfi+lBH5OvXN7+8guzB7J+3dmB2z80rX/m3aSsP59X75E/uuPzc/wC2PuYX4/LrkxZj9MH5dNfunSzqTToWYf4kf7YH8/4X9vwIWdR8+mpWCoeg43XtuDvPuvpj4syN5dq18jfID5Dxx3Zf9CvV+XoptubLrSjLoj7W7N+xonib/P4+lqRpK3I5u/3pn3gpPab2MPIWwX3h83c0v9Kuk98dsf7eSnEVUaFYHDBlOD12G/uV/uxR+8H3gd397OZtu8TkvkiINBrWqS7pMKR0qQD9PEdbDPxnzA6t/rdz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8uNmS5+HE1W9O3c3ofE4eZIlxOJyNXHUTzStF4Gij3a9xZuReRuaeY+X9pF9u9jatLHCxIUupFHkpWqw/wBqY1rrCULD4TMHtzyBue9brt7b85ttsdsBSC8gIJ0qASF8UUTWTVQxopqGWzrGbN2z1Ls7anV2xMP/AHc2R1zt7H7O2th2kM0mPxOFj+2T7mZwJKzK1s4kqayoe71FXNJIxux98TIry+3y+vt83e6afdryZ555DxkkkJZmP5mgHkKAY66DLawWUMFlZxKsMaBVCjGlQAAKeQAAHypWvSclyeiRhqNzfkm5JP8Aqm+lj/QezKRVClSuAPLoxtLMh1Z8GvRAfllPFtT5Nfy7O9FlFPDB3Pvv4qbxrLavPtP5HbKqajbuOkjDJq0dh7PpHjka4i1NYXbnMn+775sm5a97t55fkcCz3jbW7CaAy25DIaimaHrHX773JUfMvsHf7ikK/WbXeQ3CGncADpevyKmlPPz6sDp8M8MjxMpDxytHMfwZYmKsot+Lj/W99i92mAkZjx8vs65P7Hb+JHGApoQD/sen29LGigEOhEFiCAbf71x9L/4ewlI2vUW6H0EC28Wk/H5/5uqt/wCdjumHG/FvqTr7yBKnsXuyirnh51VGI2PhajI1elQRcxVlXCbm6gf48+5D9pbUy8x7nele2CzOfRnYAftAPQ39v4de7392VqsNuf2uaD+QPWv7sja1RvPdWyNjULxRVm8t6bO2fRzVCh6eKo3FuHGYiKWoTUgkghar1OtxqUEX59zdeXS2Vnf3z10QwSSGnGiIzY+eOpQAM08cf4nZQPtJp19PDBYuPB4TDYWHx+LD4rH4uLwxCCHx4+khpE8UAZhDHphGlLnSOL++YU0pnmmmb4nYsc14mvHz+3qb1UKqqOAFOnX211br3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuv//S3+Pfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691qR/8LAukKrePwY6E77x1M88/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85lmLUkniECepMzBTT5hdR+wHqR9hgNxvVioGFbWfkFFf5nHX0F/fPnqXuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r//T3+Pfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691X/8AzUfjJF8w/wCXl8t/j4lFHXZzevTO6qzZUbwU88i9hbPpRvPYLUzVEci000u7cBSReVQHRJGsfYs5G3puX+bth3USlI0uFDkGn6bnRJX5aGPSS+h+otZo6DVSorkVGR/MdfHQgd67ERSVEZWcRWqoZEKNHPGDFV08kb2aNo3DKQbEEWPvo4+WrTBH+Hh1j7PH9DucsSEhQ50n5Vqp/wAB62b/AOVt2kOzPh7h9pV1SJ9xdGbly3XNejsDUf3cqnbP7OqnTUzmE0FbJTq5spMOkfp9zByDfG62VrNmrLbsV+dBlSSfVSAPsPXEb793Iv8AUn7xG48w2sOjZ+abKLcUI+H6hR4F2vpXWiuQMgPU5PR6vA3k0gfRrfT8X/4p7HkURdgQvWKpmHh1JyR0Ffyag2dXfH7sfYu8aurjk7V2tmdjbJwuIpnyW6tz75qqYVm2qTa2DiZajJz4rMUsFXVSkpTUVNE01RJHEpb3E/3jObfbfkr2a52v/dPmG223lY2EqyyTNSheNlRUUHXJMzEeFElWdh5KGZchvuYe3Pvf7qfem9nNl+73yfc717i2e+Wt2Ej7YoLeOT/GJrudv0raEQmQGWUgDJ4AkFVynXnym3/IOyO1e6ZMJ2NB1rR7Q27gOscVTY/H9dww7dgos3Rba3bllrMvLlN35amWqzGRp4qSpqmb7dX+2jRffya8r+/mw8kWlzsHtpyzDBt73eqa8u/1bu6QPqUtEKRwRoh0xxgyBfjNJCT1+hDzT/dp+3P3kb7lzevvbc0bhzBDt8eu22GxuZLPZLa7eML402k/UbhJE9WSSUwIOBiZAiqNeP7t2ltb4+9ddu9k5oYqnzWxcLUSwQQTZLcW59yY/Gml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HXHbtNTNVpLXSrT0MHkqa+pkISOnoKVGqa6eR2sirBSxO5J/A9ktwzAUjFWOAPUngB8yadGUtdFF+Py+Z60uPkT21L3/APJbvPuiWRpKLeHYGZTbQZ9Yg2fgJTgNrwxNz+wMXj1kUX4ElveWOw7aNl5f2falFGjgUv6627nr/tj1P222Y23atv28fFHENX+mYam/methH/hOJ0hJlN7fIb5I5CmjNDtzEYHpXaU0sJeQ5XJyRbx3pU0lQH0xeCkjxcEiEFiJARYHnHj7x++eFY8vctxt3yO1zIK/hWscYI+ZLkH5dDzk20JmvL1hhQEH55P+AdbY3vE7qQOve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r//1N/j37r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+6918i3+dN8Q5PhH/ADNPk51DQUJotgb03O/fPUo8jyQtsDt6oqtxPjKdpQHaPa+62yeLNyxApAb2Ye+g/thzEvM3JWzXrNW7iTwZcU/UjxX/AGwo/r35Ax1C3O+3/S7gtygor4/ZkH5YwP8ASnpG/wAqbuiHqr5RN1vm6z7banyCwy7JLSFvtqbfuJaTJbGrJLkoj17GahD2veYL+fc08mbn+7t7WNzS3uQARX8a1pQepGpRXzp1gT9/P21k5+9il5x2y28TmDlC5N6KfE1hKBHfIPMhOyen9AnrYg3luPI4HO7e2PtDaVXv7tjfEWem2RshKkYXFS0m2UpG3JufeW6J0el25s7bH8RpzWOgmrpjKsVNBJIwsU/et+9j7Vfc79r7j3N9zr2UWrv4NpBDG0k13dMtY4IqAopaoJeQhUXuo5GnrBH7k33MPdf78/ubJ7fe2lzaWWzWEMdxuu53MiiKwtJJBGsiw18W4mkYhIY41arkA+QJeu3Jcj0KdyZemXH/ACI+a2Q29hMOqyJNiuvup6bfGXpsPs3aePx0cs8mxdp5vP1cYocTEz7j3VJC1RUv4I3mg+ZnfedPvEf3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3S0hHppZmBFfmBT16562XOT3t3zI0klT+67yc+utVDA5rwLE9Hm+GPZVV8R/lB1T3fO1RBs2my0/XvbEMHpiqOrOxZIMFm62ojBQSQbVy0lHliTfQtKx9wp9+X7ul17o/do5uOy2TS8z8vgbpagCrH6evjxrTNXh1f6h1Mf3Ove+z5R96di27drxU2bef8UkLHtV3p4TnIAAcKT8loOPW3DuuV4q6pVJUkAdtNVEweCeFxrinhcX8kU0BV0I4Ktf382+2X0UlrHLXDD8/wDi/XrvVNtHhT6fDIHp/seXRRq/EHvL5ufDjoGjRq3C9Tbgyfzj7qmRrJgtqdW09ZtbpWgrHUEwVO8e0s0zU0R/z0FDI1rLf3mz9xrkq55g9yd756eEja9ptzBGxGGuZwC2nybw0oWpkA1px6w7+/fzrByl7QWXJkctN5325XsByIIq1Y/ImtPWnV1lbK9VVSSuQXmleVyPy8jl2/2Fz76vXbhmNBRf8g65CWcfhxgfLom38xjvX/Zevhz2JkMXW/Z797YROnuvkQgVKVu6oXG58vEP1CPC7XWdmb6K0qjgkezrkXZ/35zTZJItbO2/Xk9KIe0f7Zqfs6FXKu2jc9+tUcVtYP1X9KL8K/OrU/Z1qVUUUGGxIOhvDQ0l9Ci8jrBFcIg5LSylQBfksfeTDFppOOWP7P8AiupmmkJLSEZPX0Lf5VPxrqPi38Hel9iZugWg3zujES9pdkRmNo6hd6diuu4augq1kRZlqMDi6ikxzI5fxGj0KdAUDnt7rcyrzTzzvN9C5axhYQQ/804ewEeVGYM4IpXVUitepZ2CyNjtdtE4pMw1N9rZ/kMdWKe466Oeve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r/1d/j37r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691qH/8ACtz4MN2v8Xut/nRsnDtUb4+KeY/ux2bNSJLJU5LoPsXKUlHPV1UaOfPFsHfstHWRhUvFTZKt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QRKCJLiFdKu8lTpEyBZKstWOphUMKXj/ABE+Kz/F7a2+s3vne9L278k+987i93fITuCjxkuHwuUr8JRvQbR6w6yw9Sz1m3emusMdK9Nh6WVvPVSvLWVFpZiq5r+2Httyz7ScoWHKfLNsUt4Vq7MQZJZW/tJpWGDI59MKKhaA6Rzr93fdbmr3t54u+cuaH0g9lvbj+zt4R8KIKmmKV8/Uk1Ym8xVHLX1cUUcZllmlSKONRy8juERV/pdj/rW9i25lABJOOgD2xoS3ADPWrx/NU+RdP318oH6/2tkVr+sfjnTVmx8TPSzCXH5zsKrdJOwNxIUJinWmqo0x0Egv6IXtwbe8g/bjYzs3Lq31xHp3G/IkaoysQ/s09RX4iPmOph5O2s7bs/1Eyabu7Os+RVB8C/mKsft6i/yvviw/y5+ZvVuwsliv4n1xsGrh7c7baVWNENqbOraepw+EqyjRyH+9m7RR0QUHmIyk3VWHtj3P5pHKHJe630cujcp1Nvb+viSAhmH/ADTj1N9tPXoc7HYnctzghcVgQ63+wcB/tjQft6+hSAAAAAAOAALAAcAAfiw989upg679+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvdf/1t/j37r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+690hez+tdldy9b796k7JwNHujr7s3Z+49h7225XqWo83tbdeJq8JnMZPpIdFq8dWyIHUh0JDKQwBCqxvbnbb203GylMd3BIsiMOKuhDKfyIHVXRZEaNxVGFCPkevjq/PT4a74/l//Lzuv4i7+Sep/wBHG4HqOv8Ack8ZWPfXUe4teU633hSPoWGSWv27JHDWJGXFLkqapp2YvE3voryhzNbc2cubbvls3dIg8Rf4JFw6nJOGBGcstG4EdQXzTtcm2bi06g6HYn8/M/7aob0yR+E9DV/K7+T8PRXdFX0/vbJJR9V98V1BjVrayVI6HaXaUINLtfPl3YJT0G5onGOrG+mo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vt633o444o0iiRIoo0WOOONQkccaKFRERQFREUAADgD3gSSSSSc9Sz1z96691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691//Q3+Pfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3XvfuvddEAgggEEEEEXBBFiCD/Ue/de6+ZJ/wow/lE1fwC+QlV8nujdqTxfDn5H7qq6yWjxVOBieh+6809VlM1sCaCBFhxOyd7yJPkttkBIKeT7rHAIsFO02bHs17hLzTtI2LdrlRv8AaqACeM0XAPX8TA0WSuSxVqkvRYx5z5d1f7sLVOA7vmP9gf8AGeHwAHXn687G3v0v2FtPtvq/MnBby2hkRkMTVkGShrIpFMWTwGbpCQtbgc7Ru9PUwtwVe4sQD7nGC4ubO5ivbRtN7FWnowOCp+TDB/bxHUMc3cocse5HKG/+3vPW2/V8t7jD4cqcHQjMU8DfgngcCSNx5inAkdbZfx1+Qmwfll1PQ9pbECYzJUzxYnsTYs1RFJl9gbuEV6jG1cSnyy4TIsrTY2rsEngIXiRWUTzy9v1vzBYx3EfbcgUdD8St5g/PzBGGHcuKheAXvL7Pc2fd/wCfrrkfmms9g4Mu33wUiG+tCe2RCcCaMUS5irqRwSBoKsRTZHiksQQQ1voT9DyDb8+xAjEEUPUfqyutQfLotfz8yU2K+CHyfqUqvtDU9byYlpA7RiSPL5fGY+WkJBAb7xZtAU/qJ9xf94C8+n9mueJdelzZMoP/ADUZYyB8yHI/Pqbfuj2MW4/es9jbeSDxFTefFpStDDDLIr/7Qrqr5U617/iN1qtR/L5+aHZWWq8v/B4o6bF0uGjy2Xi27kMxg8bTTY6rzG3oK2PCZipx1fuCKSkmqYJJKSZdcbKffz5e5PMap94f2F5ctba3/eMQZjKYojcJHO5WRYZypliV44WEqI4WRTpZSOvtu9i+QuTJvun/AHjfcbmPZoJ+YYVkttvmctqt2+mRXZVD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9O3FvTh0RvpDpDsX5EdsbE6L6hxP8Y7B7Dyv8OxUcqt/D8LjadRUZ/d+fkTmm27tbGB6urk4uqCNbu6gi/e9727l3ab/AH3eJtG326Vb1Zj8Ma+rue1R868AehbbwT3txHaW61mc0Hy9WPyAyevoc/DX4l9b/CroPaHRXW0clVS4VJcruvdVdHEma35vnLLFNubeWaaIaRVZWrTTDECy0tJHDApKxAnnjznzbuXO3MF5v25GjP2xoD2xRLXRGvyUcT+JiW4nqYNs2+HbLOK0hHAZPmzeZP2/yGOjT+wt0v697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r//R3+Pfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+690DfyD6A6m+UvS/Yvx+7y2jQb56r7T23W7X3dtzILYVFFVaJKavx9Ug+4xedwtfDFWY+ugKVFDXQRTxMskasDHad1v9k3G13XbLgxXsLalYfsII81YVVlOGUkHB6pJGkqFJFqp6+Tn/NU/lcdz/yp/kZU9U77OR3n0pvmbLZj49d2NRhMf2Ns+jmjM2Dzz06LR4rtLZUNTDBmqD0eUNHWwK1NURO2e/IHP+28+bV49uvhbpEFEsRNSrU4gnLI1CUJyRWvcrhYe5p5cksJDd26/oE1qPwn/Iprw4KcfCRQlfQPffY/xb7Px3a/V9XFNKYVxm69qZCWT+7vYO1JZFes21uGJCFWQquuiqwPLSVAV1NgQZI23cLrar1b6xakwoGXydQa0P8Az6eIPyJ6gz3X9quTPfPka95A56gZYtRktbqMD6iwugCEubcnyzSaL4ZYyVIrQjau6D716u+U/XVP2d1PkJXpYpYqDd+0MmUTdXXu4Wj1TYHclGp1aCwY0lYgNPVxDUjXuonfYt7st/tVntpAJRh04FWpkEfzHkRlaitOCvu37Uc9exHOM3JPPtoolYF7S8jqbXcLeuJ7d/WlBLEe+JsMKUJA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wkkH+/P4VPw8ePCTuVeVfoPD3beIq3xFY4m/0Ov42Ge8jgPw/b1UdtTa+Zz+Y27srZO3clubde5snQba2htHb1EavMbhzle4p8ZhMPRRf5yoqH9KjhI0BZiFUkSfdXMVvBcX19crFaRoXkkc0VFGSzH0H+x0NqySSKiqXmc4A4knyA63sP5UP8tXD/BvrKTee/6egzPyb7RxFA/Y+bhljrqHZGHD/e0HWG0apVKDG4mRkbJ1MR05PIoZNTRRwWwV92PcubnncxZbezJyzaufCXgZW4GeQerfgU/Ahphi3Uo7BsibXCZZlBv5B3HjpH8I+Q8/U/KnVuXuIuhD1737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvdf//S3+Pfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3RQvnH8IOgv5g/x43f8bvkTtls3s/cax5HCZ3HNFSbv683nj4pxt/f+w8zJDO+F3TgJah/G+l4KmnklpamOalnmhkPuW+ZN05V3W33faZtM6HuXOl1qCUcClQafIqQGUhgCGZ7eK5jaKZAyEeeeOOvlXfzJv5YvyQ/lcd2v1V3hjDuHrndVblX6U73w9BNDsftnA0LpJoU6p121vvGUc8X8WwU8hmppW8sDz0rxTyZ4ckc9bLz1tqXVlME3JAPFhJGtGNfsBBoSrKKMAcKQyrDPMvLUu2yyXNqrG3rX7B9vmB68RwbyJJz0t3P2j8b+wqHs/p7cMmFz0CpTZfG1Iep23vDC6w0+3N4YhXWLLYmoThX4np2s8TKyg+5Csbq7227S9spNE44ip0uP4WA/aCMqaFT6w/7ke3PI3vLyhdcje42zi52hiWikWi3FnNSgubSWhMUq+Y+CQVV1Kkjq4D5b/NjqX5b/AMtbuttvTQbF7awsnXE++Oo8xXqcjSqN4YtKvM7NrZPEd1bUkn5V1H3FMpCzoCNRR+/PMLb97Lc0h1pc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5isrG3ea7kICogqx/L09ScDz6vGk91OlraxNJdsaKqipJ/zDzJwOtbL50/zMN0fJiPKdO9CHP9d/HZpWpdwZ6VpcTv7umOJmQ/xj7d1n2zsCewaPFownq0INS1jo9z1ybyBBy/4e67z4c++cVT4o4Psr8Ug/i4A/D69Sry9ylBtBW+3LTLu3kvFIvs/iYfxcB5evVbe1dp5ncOb25sfZO3slubd26cpQ7c2htDbdA1bm9w5mtdYMfh8RjqddUs0rEf0jiUFnZUBIH9zdQ2sNxfXtwsdnEpeSRzRUUcWY/L9p8hXoWfqySIiKXmc0A4kk+Q+fW6h/KZ/lKYv4h46j7779o8RuT5S5/GyxY6jp5lym3OkNvZOIefbe2ZWQQV288hTkJmMuuoMQaakK04d6jCz3a925ub5ZOX9gd4+Vo3yxGl7lx+N/SMH+zj/2zd1Askcv8urto+ru6NfsPtCA+Q+fqfyGON6PuC+hV1737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691//9Pf49+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+690W35ZfEjoL5u9H7u+PHyT2BjOwutN3wo8tFVg02Z27nKVJhiN4bNz0AGR2vvDAyzs9HX0rJKgZ4n1wSzRSHGw79unLW52277PcmK9iODxDDzV14MpoKg+YBFGAIamhjuI2ilFVI/Z8x/q+3HXzI/5tv8j/AOR/8rHcdZvOAZru/wCHuZzD0uze/MXjTNltkrVyt/C9p97YfHQ+Pa+cVSsMGaiRcNln0lGp6h3pI83/AG791Nm52jW2m0Wu+qtXhLYanxNET8S/0a61FdVQA7RJzFyfNbyPdbelYzkqP+ffQ+ejh/AThRUb1bndn7Y7K643fvrbeL3lsnbe9du5Tem3MlSrkKLO7LGRhi3RjpqYBmqY5sLNK6qL3dFI5t7UfeB5N5g9wvYb3Y5O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Co8XHSf6L/lV8n+vKegoKeeMvTxdnZDdNFKaZkVo5Jabc6nSoKFbMpIPvM/2q3qLdfbflq9QaV8Eg1Pmkjoc+nbXrmp7+7Y+xe8/PVrI1Q80coNKDTLEr4+ytOm75U/Pv46fENKrA57Kv2j3GInFD05sCtpK3I0FSYyYZd/7jRpsTsnHByNSOZa11uEiB59y7y9yXvnNDCaCIW+2ec8gIU+vhrxkP2UX1PQV2Plndd9CyIng7f8A79cUqPPQvFz8+Hz61pPkt8q+9fmJuamzvcWdp6TauIqXm2d1LtUVFB13tBCx8U0WOd2l3DnQlvJkq8yzk30CMce592DlvZuV7ZoNrgJuXFJJnoZX/P8AAtfwrT516lnado23YoTFt8dZWHdK1PEf1z5L/RGB8+mHozoXt35Hdh4zqXofYmU7A33khFLJQ0NqfEbdxssqwNuPememH2G19t08jDyVVQRqPpiWRyFLm+b9s/Le3y7tv1+tvZLXJyzkfgjXi7nyUfmQM9G9vbXF5Mtvawl5j5eQHqx8h9vW7Z/LY/lTdY/BfBrvbdVTje0vkluChRNwdjVWOQYzZdLUQAVW0OrqOpQz4bDRM7xz5FgmQyg9UvjjYQLhJ7le6u589T/RWqta8txt2Qg90hBxJORhm8wmUTyqe4yZsuwQbWvjSESXrcWphfko8h6nifPq2n6e4m6EHXvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvdf//U3+Pfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+690zbh27t/d2Cy+1914LDbn2zuDH1WJz23dw4yizWCzeKromgrcZl8RkoKnH5LH1kDlJYZo3jkQkMCD7chmmt5Y57eVo50IKspIYEcCCMgj1GetEAggio60hv5rf/AAlPWaXcne/8rhqPF1Mj12b3F8P90ZpaLB1c8sslXVydGb4z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0aPKUXZ/UeRpppjVYeurdi1Gcxe4IzLIKXI0yo/leMsgVvkg8C42Pb7KKHl/boGLO60Tx0jbwIoi3mrlZJZ80qFqzM+kRWk0vjxbpeXcr7tdzBdKkh/Cdk8WRtNKhkJSOIU1HPaFXVrc/wAwX5Td/wDTHyo+WPxi6R7RqNm9H713f1x31SZ/aUEVFvXcdJ3301s7cuQpKbeqXr6Das7UamNKXxzs2vVJY2GdH3UeS9iT2vtZN3sxcbrt9yYNLGsS9iyg6ODNqdiCxNR5dY+e5e07Xu3P93zPfW/jX08SYaugaOwFVwCSADnHlTqp+GhocbHU1tTIqtPM1TXV1bO8tRVVMrapKirq6mSSorKqdzcvI7OzH6k+8pnd5WVAOAwBwAHoPIfy6JXlNAGOBwHAD5U4Dq3n4Ifygfkj8zTit77lgyPx++P1WyVA7A3XhZF3vvbHhgSetNlZFIJnpqmxVcrlFp6NRd4UqSAph/nv3g5a5MEtjbMu4cwio8FG/Sjb/h0i+n8CVbyJXj0e7Vy7e7pomkBisz+IjJH9BT/hOPTrcu+K3w96D+GnXsPXPRWy6fAUMpSo3DuXIuuW3xvXKKulsvvDdE0SV2YrDzoT9umpwxEEUSkr7w05q5w3/nPcW3Lfb0yPwRF7Yo1/hjQYUfPLH8RPUlWG3Wm2wiG1ioPMnLMfVj5/6qdGd9hjpd1737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvdf/9Xf49+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+690QT51/wAsf4X/AMxrZ0W1/lF1Bitz5nF0rU20u0NvSDa3buxbzCoH91N/42IZWmpPOC70FV93jJmJMtNJ7FvKnPPM3Jd19RsO4tGhNWjbuifFO5DitPxLpceTDpLc2VreKUuIQwIp+X+UfI460avnx/wl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aeih8MEU8IaZQw95eezHubyjyHyFzJFvd277pLuxkjtolJkdRCo1FjRESvaCzVwaA06jPmDYdw3PdLL6dKQLBpLscCjftY09PzPWxb8K/wCSn8W/ixLht778pB8h+6cf9tVxby3/AIujbae2MpEhJm2HsBjV4nDyQyOQlXVtW13pDLJGeACedvezmjmvxrKwb93bK1R4cTHxHX/hsuGb/SqFXyoejja+WbHb9Es3610PxMMA/wBFeA+01PVxyqqhVUBVUBVAAAUAWAAAAAA9w151PHoSdcvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvdf/W3+Pfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+690Vr5vfIqj+JHw/+S3yYrFWT/Ql0t2B2Dj4HopcjFVZ7BbdrajbdFUUUEsEs9LW7gNNFKA6WjdiWUAke/Prx4dfJWofj3id7/y7vkn8+fkJmc3ne8O3+4aDJdebqrZJqzJ5LcOQ3tI298pki8wSrbf2fy1bFUTOGMMVCrL9TeCdx91t/wD+Cb5F9neWAh2K126ebdVNKM8sJlTNK6rZQjKAe4yEGtMZGbR7ScuL92rnX3X5pBG8XV5FHtzAMSiwziJhpqFpcM0wcsCVWFXXiQTKfy/5tjfzI6L43/y3MzsHF1XYA3rtzZmKqo8RU1MeM6xx+Rk3J2L2fi89EGrNvZPbOyqDITV8QmjjqJghQOsjRoScxe1PNnKfvknuLtPMc0XJu6SPc37eIE0BFFbeVDRJInIUQuQSvAkMFZsh+WvvGeyXMX3KuY/bnnXkqzl93Nm29bTZ45Y2YTyTuI0vreZRrhmt1Lz3Sa1EhRWAeKR4ot97sn5KdedDfNzCbjl2FvDd/Uvxq6b6g+Nm2sJ1zhptyVvWFX8gM5mczmuw5MGH+9rcPsfq3pmjOQixiVWUGJmlkSCULo9jb2i5nb3Bm585wTtsf3itlbengwIXI4mhZ31NTGrHXP7e7BtkG1bdMCZhBrap7qsdNaADgq+nEmmOjSdTZHE94fNrv/vDE5bHbp2ZsPqvo3pHqLP4Wvp8vt7Kbc3vif8ATtvzcmCyVDLPj6mn3BV5vC0sssblmXEojGyhfYf96rqa4uti2SNqRhS7Cv4pGoCQeACIe7yDenS3YyqW93c6u5uB+SrSnzqz1p5EA9fLg/mddhYHvX+Zv86uw8RV42owuc+S3Y1FjHpKqOSjrqHamRXaEVdBIXb7iGrXAF9akxsWJX0299Wvuu7Hdbd7DciW860mlSWY/ISvqA+WQfnjPULe4l/4G8TSwxOY1CrUA/hxxGATSvRd8RsvBVq01QMdQSxX8ar9tC71LqpW4BS1qY8i/HHudjCYtcXnj7B0A33eacpIJmDkGi5FcUIpXFD5kUNOhFxfXuDlcIMVQsFuJZPs4F0l/pEl49C6gP6c+7KG4Kfy+fr15dwuY+1p3diOJby9Onbc+xMTjttZcUeIojXy0E1HjlpaGGaqnyWSUY2gijjjQvJLNV1cagLzcge1sl4+2bVu26vIVFvaTS1JNBojYjPpWnW1uria4tYdbMzyKKAnhWn+Dr6unxd6gouovih8Y+jKGmaliwPWvTXSUkBpRSzUu3tg7DoazddK8cSJJSVOSy9DWJVqeWZ/VfT74W3l63Md5PdXMoeTet6+jxwWztjJPOiniDM6yeJU1bUPJRTM7aEk22xDIpB23bXvM+d1OyQQu1eIjVo3SgwQfNiSC/8ANa7m696r+MPySpt29mbO2FWVXTeM2Lg8Nlc9iaHcuaw/Y26cfhOxJ9k7WDy57cedpNhrOlNT0FLPOzDSq2JPsfWo+r53vncKljtm3RqtaKiNcs5dgTRVAjiSOuKA08+grcqtrydawRlnv9xv2ZiqlpGFuqBF0iperzO5FCaivkOgf+Ff8w/4X79+VXzOqNvd1YXYGwsVsj4r0u1KzvKrx/Tg3pQ4Dam9du1e8Nn0fY9VtzcWQ2/DFDQ0klRVUlIzz2Kx6CrsJdu3Tb92gml2q9S4t4pSjMhquug7Q3BsDJWoriteiW/2i/2i8Rd4297a5miWRVkAVygJAYrxXJNA1GpmlOtX3+dVv2f5G/Aj519ZbG2Ng5Ohfht84Yu/OgO59t53+MYruTavcfau7Nl9lw7Hw9BStjabYfVu7OxRRS5OlqJaKrnF00hCzm0iMIx2HVpFa+VOgtbsE3XQksXgh3oBx71FRXgcqOA+3pJf8Imd4ZSh+THzh2HjUnkl3L0N17uSBpWlOIo6nau/qvFfeV8auEaVYt4HxgL5JNJQFQSQH93udxitlg2m18TcZW0qzD9KIUNZJSDWi40ovdI1FqoqwF1nFatcCa9kpaoO5Qf1HyKKnlmhqxwozQ8Dvv8Axl6X2P1Fl/kvk9oLmnyXb/yS3b2tv2uzFbT1iV+9crs/Ye3q6bEpTm1Bikx22qVVp2CmOYSWGkj2p2+wTbbKC0SV5CKszuas8jEtI59NTEkKKKooqgAdNTztczSSsoUcFA4KqiiqPWg4k5Y1JNT0aj2s6a697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuv//X3+Pfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691pT/8ACjn+c/W5TPZj+Tl8MtudddzdifJPY8HXne3Yb5qTclD1qOwckKCDrnbdDgphjY9+x7fpnyOWr62eaDB0NTEft2qdbUyTdd02zl3Y965o365EGw7dbvNPIeIRQTRB+J2I0ov4moOJAJtsGxbrzTvu0ct7FbGbeL64SGJeALMaAsfwoOLtSiqCxwCRrkfOPZtV1v8AH/4jfylOspqntnujN5nDbuy+epBTYqmxcIyOeqUFPQ618NDV5CtrpoZKl9UONxxllZncEYVexe8Q8x8/e7f3tuZEXaeS7eGS3jibVI0h0RLl6ZdUWJWCDvmm0oAqmuevvZsM/L3IftP91Hl5zunOF1NHPK4Cxqqh7gjtxpRnkmYGQ1jgg1SFi1Rfn/Iy/l/9U/F75HfOH5XbKSnyGMxOM2Z8bOlUlgnkl2fubN7axO6+/Tj6+d3Wq8EsONp450KyU6VctO17kkK85e/3NfMvsvypbb5VOaNzN1rcUHiWaSskMpUU06wXjYcHKBxQY6h/3W9qeV+RfeveeXeWZtexWUFrIyGp8CeSJWaDUa1PwzeRVZDGalSTbPtfEVW4fkVumr++ip6yf+Y98FYxXP5TOcbsr42br3dLjlETq+rIGSqh/wBTpqmLgoCPc9/dFVIvZiCTTWWTc78sTxLa41r+QAp1AnuQNfNUgrQLFCB9gUmnzz+3qwX4mfDnpPEbU3/vDauP7I2LhO3/AJCd1dtb06mod7ZfCdczbpyG7MltCeKg2riZKRMXtWal2vT18WOppYaR62aWdorSmMT1e7Fs+4X67jf7dHNeKqqC4LCi10nSTpqKmhp59BSG4miiEMUpWOpNBTBbj8xXFehQ7H/lofy9e2sbLiuwPhV8ZM7TTSGV5k6a2NhsmJWq/vpJY81gcNi8xDJPV3kkZJ1MrE673Nx9tXO/OGyCNdq5lvYIkXSFWV9AUCgAQkpQDgNNB5dFtxtthdkG5s43b1KiueOeP8+iz5v+Qr/KFz71klZ8GeqKWathEMkuFrt84DwhYvCklHFhd20NPRyovOqNFLMNTXPsRw+8fuZBp0c3XJAP4hG37SyEn9vRc3LOxN/yz1H2FgP2Bqfy6Dmj/wCE6P8AKKokjSL4vu/iMhVpu0O05HPkYMdZ/vgA+m1hf6D2af6/HugK6eYqf82of8qdJ15P5fUUFjj7T/n6IB21/LZ/kobT7voeo90fH/cXSG0uvM/hN/v23DV9+19f3LunaNagHW/V+5MJU7qop9m7G3Isbbqe1PWyZaGGip1KLNOoe3v3t9z9/d+U7/f5ZNovbNzMAIkUqsiARnSivVyakghdK6eLU6W23KnLtrCd0jtQt1DKFXiT3I1WGSKAY+EkE1xx6HHcuDy/ZVJjaLoPG/zau/sbkOyM46Znsz5F5L4n9KzY6Fcsa6om39vbBYPsOpxE0STaP4Th555F1jyISFbHiGKG2bZ9Bs45f6xXTwlU8UlQsploQWVJW7u5yMhxjofJHPM24RlZih2iHxASVDKTHoByhpXQToDY0drdEb7Y+Cm7RU1m4d7ZfrfqWpmkrJKrb/xux26d0dk1UNZBCgot3fLzv6r3d3HkJ0YsksmDgw8bC/jfSRYKb3uEO473v0TRSXBihgQ+O+qMMQ0gIt1ogYL5uWDDy6lnlnZbiw2naXWeG1E0krD6ZAspAKqQ1y+p6E4IQKcfF0Sjuv4q9SUm56foHbPWezKCiym7+nNjxvksJTbs3PufMZreu0Tmspm907ljzO5s5nsv97USTSzVTM0MRRdK8CNeSbncN45x5UnuLmSQy32oKKqiRhm7VjTSgVQvACmamvQ+53h27Zfb/nFbS2jiAsWQs3c7ytpXW0r6nLEtUEmvkKdbKH83X4o7W7J6XxmAgxuH2z112T1f2V8Ld8TY7F09BhNi4zv2kxbdI78eiooYMfi8NsP5GbX20JnAVYYMpIQANRGYySaxIprk1/z/AMuHWFdxai3NrOiglFCnAHnUHhjNa/b1p0/8JC9wyfHj+YX80utOwsNkqHtfHfHjc+zqHrRY77pzfYHXva+3afcGx6GlRZVXL0lXSzLNJIVp6ZIZJJXVFv7YFaMK+Y6NNQJRhwIPX0dOmthVew9pVS5pMeN37x3Jnuwd9SYsN9k+7t21f32Rp6eViPuqfD06wY+GfREZ4aRJDGjMQNE16uBQdCz711vr3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de6//Q3+Pfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737h17qjT+Zp/Ot6n+GKZrqLpNdvd1/KGMvQ1u3/AL6So676iqCgY1faeWxNTFU1GdiRw0O26GaPIyEg1UtDCySuDefOf+XPbeyjn35jNvEqB4LGM0mlU/DJI1CLeAjIdgXkFPCjYEumaf3Q/uNe7P3uN6FzskD7P7WwOVut7njJh1L8UFjGaG8uAaK2kiCEn9WTUpjJs/5bX8xPrX+YV0su78JHS7U7d2VHjMR3Z1W1U09Vs/clZTyGmzGEkmtPl9gbrNJNPiK+1yqSU04Sqp540O+XN/2nm7YL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de9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3X/9Hf49+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Wo1/Oy/nXdjdYdh7/+GXxirq3YdZtSpoNsdr91YKf77feQzmUwFDnK/YPVFPRCQ7YlxFDlEhyucdjkIqlZqekSleIVbBHmLmHmCDcpuU+RbS0bmlNvF3dX17LDBYbTbSMFjlmeciJp5AyGISVVfFj0RTSNSLph9zf7n3t7zpyntH3gfvEX19L7YXO7ybftWw7bbXF1unMF7blvFjWK2DTG0jMcviJEql1hkMs0UNQ2obM7bzyKfcU2ahwVOa3JZaXJmtx9Tns3XTPKzVs00yZKtdJZJampmkY+Wd9TlmufcHRyz+zWx79zNNzhs+6e9W8XiJBPDLBuzbfYpqe7u3kdZbdLm9fwreEMHmEHjlRGWBPcWz2jbPvA8wcn8gbZ7bcxct/dg5X2yWS4tLi3ueXo9z3J9EO37ekMb293JZbbD9ReXLIY7drv6YSNNoZetl7+Qx/Ly+XNT3H118vMPufcvRXRG1PuKR85n6aWr3F8kdo1MrfxLYeK25XNSrWdc1kkcTHcFchRJqeKXGLUTJ9zBIftfy9zdFvXMPuJzRDb7PHvMQJ2i2h8GKZmQabqWCpWzAes8aLSVndgqRW0lH5Vf3kv3ivu+blyLsH3XeQobjnPm3lm4ovMl3dfUybWUlbVZQ3oUPuMvhn6SarGJIkHjSS3Cd2y5P8AzZfgZi/kR2F8Yd296YbYHZvXG46XaOWqd+0VdtfYeU3NLR0lVW4TA9h5GJNo1eRws9WKWsimqqdoqxJIlDtG9pUF/tDbrJsC75Zf1hSNHa1MqpOFkTxE0o+kSMyENoiLuAy1UVHXLlfYX3ol9uNq93bX2w3m49tb1pliv4Ld54SYHKSMwh1yxxhlakskaxMFaj46sPxuUxmZoabKYfI0OWxlbGJqPI4yrgr6CrhNwJaaspZJaeeMkH1KxHtZLFLA5ini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ryF7UP4VpPOxa6slZlAdYpyzxOpKmOQKKKgrdv7XdY0de9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691//09/j37r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3VQX887vU9I/y5u46PH5KTH7n7qnwXRm2zS17UGQlXfdYx3g9E8as8xpOvMZl5pI/SHiRlJ5sSHm7fF5X5N5u5iMmia2sJFiNK/r3AFvDT0ZXl8RTxBStMdZPfcv8AaqT3n+9J7Mcim3Mm2neI727AAOm027/HJWKtVWUvFFE6tgrIRnh1oIfFPpvLfJL5O7P+Oe05aaqqO3eydp4GXNUhnkbEUebkC7wNZLShmaXa+0cRV5IeNrxQR+rSQPcLR8lS897L92245htbqwnt4bmzlspVKibbNvka/wD3pbIR+nHdfUSWjl1CzXMQdGcM+n6AfdT32277u+x/fw5h5a3Hb91tWW13K23CBw7xb9u8CbTHsN3KraZZ7U2kN5Asbk21pP4Uqxsqa/oafNv+VV8XPmT1FtrZO4MNF1nvHqvZ1FtPqPuPalLSR7n2FgMFjo6TGbey6VDwUu8NhQw0ymfFV7+NbNLTS0tQfOJ85i2faOdrO42jmfbBdWk0jMmiiT28rmviWkulmietKqA0cgoskb0XT85vsP8AeO92vu085Nz57Zc1PBdyGt9bzkyWW4xipdb6EkK5bJFwNM8TUZX0go3zpt1YqlwW59yYHH5zGbooMDubcmAx+6sItRFhN2Y7CZuuxVBuvCxVRNVDhtzUlIldSpIS6wTqGJPJwa5r2Wx5b5p5h5c27el3KysLpoUuQhjEugDVVCTRo3JicqWRnRmRipB6+wL2g553z3P9p/bj3I5i5Nm5d33fdogvJttlkEr2jTLqCGQBaq60kUMoZVcKw1A9WT/ylvgbUfO75T4Ta+5sdPL0X1ZHjewe9K4I60uSwkVbIu2OtlqFki01nZOXopIJgpLLh6SvcWcR3H3svyYvMfMc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EgALBpL/AEv7IfeDZ5N79rebo4bYyTWYhvAQKlRDKI5GOMKIp3LcBj1p0J/7qvnxeS/vkcjbfcXKJZ7/AGV7tpDGmuWSIXEIX+lW3ag8+qL/AOQD2HufZf8AMq2DtvA4rcOaxHaXVnae0d702CjWalwuExVDjd3YreO542W0WAw25MHTY/zFk0VWXiUamcKYp+6rLdzSe5O2+Ef3X9Bb3DSkHQk8NwEiTVSgkmjmnCLxbS3kpI6Rf32mx8vz+0Xs5zJc3tvHzVacwywwRM1J57e4t2+oES8WSBkillPBRTzI639puIpT/wA23/6FPvJ1PjT7R183tyaW1wf6Df4D186L4P8A8szvj+YX3BvR9modkdG4btDe0G/++cxQvV4CiRd5Zl67AbApCY4d977MV1+3ilWhxzMslbNH+3BPjfvHsve88+7fuVzLzBLJYcpDfbvT20nuys7akt1YUSOldVy4KJwRZXBQfR7v394lyL91j7pnsR7fcmJbb974Scm7dptQ+q120NbDTPuLoT3qf7OzQiaVh3GOMM43t/iJ8MuhPhF1ZSdVdD7TXDY+SSOv3VunKyR5PfHYG4FhWGXcW9dxGGGfK5BlBWKJFio6KL9qlhhhAQZE2lpt+2WFrtGzbdFZ7NAKRwRghFwKsSxLPI9AZJXLO54mgUDgF7ke5vP3vBzfuXP3ubzRcbxzddk655jhErUQwRjsgt0rSOGMBF4nU5Z2NV7d6A3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvdf/X3+Pfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3RU/kH8HfiX8p6WSLvfobr7fmRaFoIN01GGjxO96BWAAON3xgWxm66Bo7enx1igc8WJBtd+BuVqLDd7K3vtvx+lcxJPGKfwrIraK+ZQqeGcCgz5E9x/cL2u3Jd49teed22Dcw1ddjcy2+o/8MjRhFN8hKjgenVEHyJ/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91737r3X/9Df49+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3TXm6XJ1uFy9HhcmuFzFXjMhTYnMPRxZFMTk6ikmioMm+PnZIa5aCqdJTC5Cy6NJIB9uwNGk0TzR64QwLLWmoAior5VGK+XVXUsjKGIJByOI+Y61I90/8Jet0bqM9fnvmdh9057LZKrzu4stuHpCo8uV3Dk62bI5jO3ouyFkiyGUyFTLPKwYfuStbg29gOH222jauZ93525b5+5lseabuSVnlVrUhxMSzxyoIwskeR+mwKdqmlQKdRLD+9C5ik9uOV/aPmj7sfI24+3uz2ttBa2zTXo8EWsaxxSxPp1QzUBJkjZWGt1B0sam8/lkfyPux/wCX38paHvXI9+dfdgbRpOvd/bIfa2D693FtvNSSbuqtv1dJXLkMlurO0iCklwd5Ra7h7C31BttXLCbdv2/817jzXuO6b/uFrDDI1xHBGP0nUhv0aAgKoRVCDiWLHA6iP7x/3zLD379peSfaPZ/ZrbuVti2Pd5L6EWt5cXKlpYZI3SlwgYamlZyS7eQAFM0EfzUfiJ8saH5v/LrtnKfHrunK9dbq7dr917d7BwWwtw7u2rk9pZDF4THYGup81tehy9PBTQUuPWneObxS0rRFZVWwLQD73e2nuFzZzlLzFy7y1Je7Q1pawp9OySSFobdFkBgVzMDr15MdG4qTXrqx/du/e8+6x7afdw5P9rOePd3bdl52trq9nngvi9uoNxcs6sk0iiFlYEUIkBrUECnWwf8A8JyqsYL4F9q1OTgrKQ4H5G9lTZOlqaOppaymOP2PsCoq4JKWqihnSohCFWQqCHBU8ggTV7R7Ju23+3nJmy7pt01pueudTHMjRuNd1IFJVwCAa4NM565ef3ofNPLfM33tedOa+Vd8tN02CbZdueOe1mSeKQLBJUJJGWUkUoRXzB4HrRu7k3DQ9lb83RkaOlhok7Q7D372BQS1yLFNh8ZuTd2T3UYqIKyv/Go6XMJEiI3oszN6VN485W33duXPcf3199p9xupdu2G/ktpLKDI3Ce5ee3tY7+OhjXa0aEyX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8rtyTznzXyd4qFtn3W5tUkhckf4pcPHFLFIpBBpGsiOpDKaFWqAeten5i/8ACYmh3l2lR7q+H/YWyNmdd5eapbJ9cdzzbvy6ddtNULUrT7H3BhKfJ5TdWzw+rxYfNMZ6JgBHWyRERxB9+XoovrZOTOcb/lI3j67yHb7eGa2nkCGP6m1jkkiO2XjIxSSW0ZUdaaUjC6Wzl9t/v/7nt2w7Xsv3gvaHb/cu/wBntxBtV/fXMltexQeIsgs91eMFN3sI5EEkUV3HIyOchzVyaT4Nf8J4tjfHLuXr/vbvvu1O9871nkKXc+0OtsLsCn2d1rQb6xsYbA7py0mSzm5M/uSTauQP3uOpnalp4q+GCokWRoUUFXKXtx7d+3d/PvXKltudzzK0bot5fTRM0IlBWVoYYYkVJXQlPGaSRlVn0BXIcFP3lv7xn3++85yjd+3G/WWz7B7cTyxNNY7akpa4WE1jinuZWDtBq0s8CosblVDVUaetkj2J+sC+ve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r//R3+Pfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3TRXYLGV2NzGKamSmps9TVtNk3oVWjqJ/4hStRVFQZ4FV/vDTmwlN3Gkc8D2+tzMJYZjIWeOmmpJoFNQBXyHp00IYlRo0jUI1agAAGvE09T5+vWq93Z/wlz60zONrY+jPkrunEeGnX+Cba7o2fiN8Y2GohYLBE+6tqTbNzlGn2t0NQaWsnDeo67lfcfWPtvsex77PzPyZzHvnL/MEwYSTW06zpJ4hLSCWCdR4yMxqYpJtBoCe4auunOz/AN6D7nbpyltHt972e0fKHO3JdmsSxxzwy2M8PgIEgeCeFpfBnRRpE8aJIASAaMesf8sj+Uf84P5efzo2LvzK47qjevRFVtXf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7r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvdf/0t/j37r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3XvfuvdQ6/HY/K0dVjspQ0eSx9bC1PWUFfTQ1lFV07izwVNLUJJBPC4PKspU/ke3YJ5raZLi2maOdTUMpKsD6gihB+w9NyxRTo0U0avGeIYAg+eQcdEUz/wDLA+Bud7d2J3xT/GvrzaPbPXO9Nvb+25u/rygm6+nl3FteqetxMu4MVs+ow+B3PSR1T+R4chS1CyOqsfUqkGV1vd1uHhPu1vbXt1ErCKa4giluIS/Forl1M6Nx4SUzw4UFO18688bHsO7cq7LzvvFpytuCeHdWUd5OLSeM8Y5LYuYSh/hVF9OBIJ9/ZR0GuqYcb/Iy+G2e+SXc3ya76pNwfIPc/anbe6O0MTsXedQ2J6r2VHuSda0YKXZmCqYKffclFXPNJ9zm5KqGQOoFLHoJdy1seUtq3WXmPZ+TbJOapki8W8uFF3KJIwF12yzKYrXUFBPhxmWtT41CAs7X33nvf6+9seW/ZiL3Ov7D2x2qF4obGwY2QlR3dz9XNCwuLghnNAZFjAx4Z6t+2vtLaux8FQbX2XtrAbR21ioRT4zb22MPj8Bg8dABYQ0OJxVPS0NJEP8AUpGo9u3d7eX8xub67kmuCKFnYu1BwFWJOPLOOoFjhihDCKMLqYsaDix4sfVj5k1J8z0oPabpzr3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r//09/j37r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvde9+691737r3Xvfuvdf//Z" - } Catch { - Write-PScriboMessage -IsWarning -Message "Cover page images are not supported for reports generated on Linux or macOS." - } -} - -# Add Report Name -# Position Report Name -BlankLine -Count 2 -Paragraph -Style Title $ReportConfig.Report.Name - -# Add Company Name if specified -if ($AsBuiltConfig.Company.FullName) { - # Position Company Name - BlankLine -Count 1 - Paragraph -Style Title2 $AsBuiltConfig.Company.FullName - BlankLine -Count $LineCount -} else { - BlankLine -Count ($LineCount + 1) -} - -# Add Paragraph Runs -Paragraph { - Text 'Website:' -Font 'Trebuchet MS' -Size 10 -Bold -Color '223F8C' - Text 'www.LosPollosHermanos.com' -Font 'Trebuchet MS' -Size 10 -Bold -Color 'F30E0D' -} -Paragraph { - Text 'Locations:' -Font 'Trebuchet MS' -Size 10 -Bold -Color '223F8C' - Text 'New Mexico, Arizona, Utah, Colorado' -Font 'Trebuchet MS' -Size 10 -Bold -Color 'F30E0D' -} -PageBreak - -# Add Table of Contents -if ($ReportConfig.Report.ShowTableOfContents) { - TOC -Name 'Table of Contents' - PageBreak -} \ No newline at end of file diff --git a/Samples/AsBuiltReport.Sample.Style-2.ps1 b/Samples/AsBuiltReport.Sample.Style-2.ps1 deleted file mode 100644 index 7362eb1..0000000 --- a/Samples/AsBuiltReport.Sample.Style-2.ps1 +++ /dev/null @@ -1,125 +0,0 @@ -# Sample Document Style 2 - -# Configure document options e.g. page size, margins, default font, page orientation -# It is recommended to use a web safe system font. If the configured font is not installed on the -# system from which the report is viewed then a substitute font will be used. This may not result -# in the desired look of the document -DocumentOption -EnableSectionNumbering -PageSize A4 -DefaultFont 'Tahoma' -MarginLeftAndRight 71 -MarginTopAndBottom 71 -Orientation $Orientation - -# Title & Heading Styles -Style -Name 'Title' -Size 24 -Color '00785F' -Align Left -Style -Name 'Title 2' -Size 18 -Color '00A956' -Align Left -Style -Name 'Title 3' -Size 12 -Color '006A91' -Align Left -Style -Name 'Heading 1' -Size 16 -Color '00785F' -Style -Name 'Heading 2' -Size 14 -Color '004B6B' -Style -Name 'Heading 3' -Size 12 -Color '00567A' -Style -Name 'Heading 4' -Size 11 -Color '00648F' -Style -Name 'NO TOC Heading 4' -Size 11 -Color '00648F' -Style -Name 'Heading 5' -Size 10 -Color '0072A3' -Style -Name 'NO TOC Heading 5' -Size 10 -Color '0072A3' -Style -Name 'Heading 6' -Size 9 -Color '0072A3' -Style -Name 'NO TOC Heading 6' -Size 9 -Color '0072A3' -Style -Name 'NO TOC Heading 7' -Size 7 -Color '0072A3' -Italic -Style -Name 'Normal' -Size 10 -Color '000000' -Default -# Header & Footer Styles -Style -Name 'Header' -Size 10 -Color '000000' -Align Left -Style -Name 'Footer' -Size 10 -Color '000000' -Align Right -# Table of Contents Style -Style -Name 'TOC' -Size 16 -Color '00785F' -# Table Heading & Row Styles -Style -Name 'TableDefaultHeading' -Size 10 -Color 'FAFAFA' -BackgroundColor '00785F' -Bold -Style -Name 'TableDefaultRow' -Size 10 -Color '000000' -Style -Name 'TableDefaultAltRow' -Size 10 -Color '000000' -BackgroundColor '47CA82' -# Table Row/Cell Highlight Styles -Style -Name 'Critical' -Size 10 -Color '000000' -BackgroundColor 'FEDDD7' -Style -Name 'Warning' -Size 10 -Color '000000' -BackgroundColor 'FFF4C7' -Style -Name 'Info' -Size 10 -Color '000000' -BackgroundColor 'E3F5FC' -Style -Name 'OK' -Size 10 -Color '000000' -BackgroundColor 'DFF0D0' -# Table Caption Style -Style -Name 'Caption' -Size 10 -Color '000000' -Align Left - -# Default Table Style Properties -$TableDefaultProperties = @{ - Id = 'TableDefault' - HeaderStyle = 'TableDefaultHeading' - RowStyle = 'TableDefaultRow' - AlternateRowStyle = 'TableDefaultAltRow' - BorderColor = '00785F' - Align = 'Left' - CaptionStyle = 'Caption' - CaptionLocation = 'Below' - BorderWidth = 0.25 - PaddingTop = 1 - PaddingBottom = 1.5 - PaddingLeft = 2 - PaddingRight = 2 -} - -# Table Styles -TableStyle @TableDefaultProperties -Default -TableStyle -Id 'Borderless' -HeaderStyle Normal -RowStyle Normal -BorderWidth 0 -TableStyle -Id 'CoverPage' -HeaderStyle 'TableDefaultHeading' -RowStyle Normal -BorderWidth 1 -BorderColor '00785F' - -# Cover Page Layout -# Set Header & Footer, if enabled in report JSON configuration -if ($ReportConfig.Report.ShowHeaderFooter) { - Header -Default { - Paragraph -Style Header "$($ReportConfig.Report.Name) - v$($ReportConfig.Report.Version)" - } - - Footer -Default { - Paragraph -Style Footer 'Page of ' - } -} - -# Show Logo image, if enabled in report JSON configuration -if ($ReportConfig.Report.ShowCoverPageImage) { - Try { - Image -Text 'Sample 2 Logo' -Align Left -Percent 30 -Base64 "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" - } Catch { - Write-PScriboMessage -IsWarning -Message "Cover page images are not supported for reports generated on Linux or macOS." - } -} - -# Add Report Name -# Position Report Name -BlankLine -Count 12 -Paragraph -Style Title $ReportConfig.Report.Name - -# Add Company Name if specified -if ($AsBuiltConfig.Company.FullName) { - # Position Company Name - BlankLine -Count 1 - Paragraph -Style Title2 $AsBuiltConfig.Company.FullName -} -PageBreak - -# Add Custom Tables -# Document Control Table -Section -Style TOC -ExcludeFromTOC 'Document Control' { - Table -Name 'Document Control' -List -ColumnWidths 30, 70 -Hashtable ([Ordered] @{ - 'Title' = $ReportConfig.Report.Name - 'Author' = $AsBuiltConfig.Report.Author - 'Version' = $ReportConfig.Report.Version - 'Status' = $ReportConfig.Report.Status - 'Release Date' = (Get-Date).ToLongDateString() - }) -} - -# Version Tracking Table -Section -Style TOC -ExcludeFromTOC 'Version Tracking' { - Table -Name 'Version Tracking' -ColumnWidths 12, 22, 22, 22, 22 -Hashtable ([Ordered] @{ - 'Version' = $ReportConfig.Report.Version - 'Remarks' = $AsBuiltConfig.Report.Status - 'Change Requested' = "" - 'Pages Affected' = "" - 'Released' = (Get-Date).ToLongDateString() - }) -} -PageBreak - -# Add Table of Contents -if ($ReportConfig.Report.ShowTableOfContents) { - TOC -Name 'Table of Contents' - PageBreak -} \ No newline at end of file diff --git a/Src/Public/New-AsBuiltConfig.ps1 b/Src/Public/New-AsBuiltConfig.ps1 deleted file mode 100644 index f6419ab..0000000 --- a/Src/Public/New-AsBuiltConfig.ps1 +++ /dev/null @@ -1,269 +0,0 @@ -function New-AsBuiltConfig { - <# - .SYNOPSIS - Creates As Built Report configuration files. - .DESCRIPTION - New-AsBuiltConfig starts a menu-driven procedure in the powershell console and asks the user a series of questions - Answers to these questions are optionally saved in a JSON configuration file which can then be referenced using the - -AsBuiltConfigFilePath parameter using New-AsBuiltReport, to save having to answer these questions again and also to allow - the automation of New-AsBuiltReport. - - New-AsBuiltConfig will automatically be called by New-AsBuiltReport if the -AsBuiltConfigFilePath parameter is not specified - If a user wants to generate a new As Built Report configuration without running a new report, this cmdlet is exported - in the AsBuiltReport powershell module and can be called as a standalone cmdlet. - .LINK - https://github.com/AsBuiltReport/AsBuiltReport.Core - .LINK - https://www.asbuiltreport.com/user-guide/new-asbuiltconfig/ - #> - - [CmdletBinding()] - param() - - #Run section to prompt user for information about the As Built Report to be exported to JSON format (if saved) - $global:Config = @{ } - $DirectorySeparatorChar = [System.IO.Path]::DirectorySeparatorChar - - #region Report configuration - Clear-Host - Write-Host '---------------------------------------------' -ForegroundColor Cyan - Write-Host ' < As Built Report Information > ' -ForegroundColor Cyan - Write-Host '---------------------------------------------' -ForegroundColor Cyan - $ReportAuthor = Read-Host -Prompt "Enter the name of the Author for this As Built Report [$([System.Environment]::Username)]" - if (($ReportAuthor -like $null) -or ($ReportAuthor -eq "")) { - $ReportAuthor = $([System.Environment]::Username) - } - - $Config.Report = @{ - 'Author' = $ReportAuthor - } - #endregion Report configuration - - #region Company configuration - Clear-Host - Write-Host '---------------------------------------------' -ForegroundColor Cyan - Write-Host ' < Company Information > ' -ForegroundColor Cyan - Write-Host '---------------------------------------------' -ForegroundColor Cyan - - $CompanyInfo = Read-Host -Prompt "Would you like to enter Company information for the As Built Report? (y/n)" - while ("y", "n" -notcontains $CompanyInfo) { - $CompanyInfo = Read-Host -Prompt "Would you like to enter Company information for the As Built Report? (y/n)" - } - - if ($CompanyInfo -eq 'y') { - $CompanyFullName = Read-Host -Prompt "Enter the Full Company Name" - $CompanyShortName = Read-Host -Prompt "Enter the Company Short Name" - $CompanyContact = Read-Host -Prompt "Enter the Company Contact" - $CompanyEmail = Read-Host -Prompt "Enter the Company Email Address" - $CompanyPhone = Read-Host -Prompt "Enter the Company Phone" - $CompanyAddress = Read-Host -Prompt "Enter the Company Address" - } - - $Config.Company = @{ - 'FullName' = $CompanyFullName - 'ShortName' = $CompanyShortName - 'Contact' = $CompanyContact - 'Email' = $CompanyEmail - 'Phone' = $CompanyPhone - 'Address' = $CompanyAddress - } - #endregion Company configuration - - #region Email configuration - Clear-Host - Write-Host '---------------------------------------------' -ForegroundColor Cyan - Write-Host ' < Email Configuration > ' -ForegroundColor Cyan - Write-Host '---------------------------------------------' -ForegroundColor Cyan - if (-not ($SendEmail)) { - $ConfigureMailSettings = Read-Host -Prompt "Would you like to enter SMTP configuration? (y/n)" - while ("y", "n" -notcontains $ConfigureMailSettings) { - $ConfigureMailSettings = Read-Host -Prompt "Would you like to enter SMTP configuration? (y/n)" - } - } - if (($SendEmail) -or ($ConfigureMailSettings -eq "y")) { - $MailServer = Read-Host -Prompt "Enter the mail server FQDN / IP address" - while (($MailServer -eq $null) -or ($MailServer -eq "")) { - $MailServer = Read-Host -Prompt "Enter the mail server FQDN / IP Address" - } - if (($MailServer -eq 'smtp.office365.com') -or ($MailServer -eq 'smtp.gmail.com')) { - $MailServerPort = Read-Host -Prompt "Enter the mail server port number [587]" - if (($MailServerPort -eq $null) -or ($MailServerPort -eq "")) { - $MailServerPort = '587' - } - } else { - $MailServerPort = Read-Host -Prompt "Enter the mail server port number [25]" - if (($MailServerPort -eq $null) -or ($MailServerPort -eq "")) { - $MailServerPort = '25' - } - } - $MailServerUseSSL = Read-Host -Prompt "Use SSL for mail server connection? (true/false)" - while ("true", "false" -notcontains $MailServerUseSSL) { - $MailServerUseSSL = Read-Host -Prompt "Use SSL for mail server connection? (true/false)" - } - $MailServerUseSSL = Switch ($MailServerUseSSL) { - "true" { $true } - "false" { $false } - } - - $MailCredentials = Read-Host -Prompt "Require mail server authentication? (true/false)" - while ("true", "false" -notcontains $MailCredentials) { - $MailCredentials = Read-Host -Prompt "Require mail server authentication? (true/false)" - } - $MailCredentials = Switch ($MailCredentials) { - "true" { $true } - "false" { $false } - } - - $MailFrom = Read-Host -Prompt "Enter the mail sender address" - while (($MailFrom -eq $null) -or ($MailFrom -eq "")) { - $MailFrom = Read-Host -Prompt "Enter the mail sender address" - } - $MailRecipients = @() - do { - $MailTo = Read-Host -Prompt "Enter the mail server recipient address" - $MailRecipients += $MailTo - $AnotherRecipient = @() - while ("y", "n" -notcontains $AnotherRecipient) { - $AnotherRecipient = Read-Host -Prompt "Do you want to enter another recipient? (y/n)" - } - }until($AnotherRecipient -eq "n") - $MailBody = Read-Host -Prompt "Enter the email message body content" - if (($MailBody -eq $null) -or ($MailBody -eq "")) { - $MailBody = "As Built Report attached" - } - } - - $Config.Email = @{ - 'Server' = $MailServer - 'Port' = $MailServerPort - 'UseSSL' = $MailServerUseSSL - 'Credentials' = $MailCredentials - 'From' = $MailFrom - 'To' = $MailRecipients - 'Body' = $MailBody - } - #endregion Email Configuration - - #region Report Configuration Folder - if ($Report -and (-not $ReportConfigFilePath)) { - Clear-Host - Write-Host '---------------------------------------------' -ForegroundColor Cyan - Write-Host ' < Report Configuration > ' -ForegroundColor Cyan - Write-Host '---------------------------------------------' -ForegroundColor Cyan - $ReportConfigFolder = Read-Host -Prompt "Enter the full path of the folder to use for storing report configuration files and custom style scripts [$($Home + $DirectorySeparatorChar)AsBuiltReport]" - if (($ReportConfigFolder -like $null) -or ($ReportConfigFolder -eq "")) { - $ReportConfigFolder = $Home + $DirectorySeparatorChar + "AsBuiltReport" - } - - #If the folder doesn't exist, create it - if (-not (Test-Path -Path $ReportConfigFolder)) { - Try { - $Folder = New-Item -Path $ReportConfigFolder -ItemType Directory -Force - } Catch { - Write-Error $_ - break - } - } - - #Add the path to the folder to the report configuration file - $Config.UserFolder = @{ - 'Path' = $ReportConfigFolder - } - - # Test to see if the report configuration file exists. If it doesn't exist, generate the report configuration file. - # If the report configuration file exists, prompt the user to overwrite the report configuration file. - $ReportModule = Get-Module -Name "AsBuiltReport.$Report" -ListAvailable | Sort-Object -Property Version -Descending | Select-Object -First 1 - $SourcePath = $($ReportModule.ModuleBase) + $DirectorySeparatorChar + $($ReportModule.Name) + ".json" - $DestinationPath = $($ReportConfigFolder) + $DirectorySeparatorChar + $($ReportModule.Name) + ".json" - if (-not (Get-ChildItem -Path $DestinationPath)) { - Write-Verbose -Message "Copying '$($SourcePath)' to '$($DestinationPath)'." - New-AsBuiltReportConfig -Report $Report -FolderPath $ReportConfigFolder - } else { - try { - if (Test-Path -Path $DestinationPath) { - $OverwriteReportConfig = Read-Host -Prompt "A report configuration file already exists in the specified folder for $($ReportModule.Name). Would you like to overwrite it? (y/n)" - while ("y", "n" -notcontains $OverwriteReportConfig) { - $OverwriteReportConfig = Read-Host -Prompt "A report configuration file already exists in the specified folder for $($ReportModule.Name). Would you like to overwrite it? (y/n)" - } - if ($OverwriteReportConfig -eq 'y') { - Try { - Write-Verbose -Message "Copying '$($SourcePath)' to '$($DestinationPath)'. Overwriting existing file." - New-AsBuiltReportConfig -Report $Report -FolderPath $ReportConfigFolder -Force - } Catch { - Write-Error $_ - Break - } - } - } - } catch { - Write-Error $_ - } - } - } - #endregion Report Configuration Folder - - #region Save configuration - Clear-Host - Write-Host '----------------------------------------------' -ForegroundColor Cyan - Write-Host ' < As Built Report Configuration > ' -ForegroundColor Cyan - Write-Host '----------------------------------------------' -ForegroundColor Cyan - $SaveAsBuiltConfig = Read-Host -Prompt "Would you like to save the As Built Report configuration file? (y/n)" - while ("y", "n" -notcontains $SaveAsBuiltConfig) { - $SaveAsBuiltConfig = Read-Host -Prompt "Would you like to save the As Built Report configuration file? (y/n)" - } - - if ($SaveAsBuiltConfig -eq 'y') { - $AsBuiltName = Read-Host -Prompt "Enter a name for the As Built Report configuration file [AsBuiltReport]" - if (($AsBuiltName -like $null) -or ($AsBuiltName -eq "")) { - $AsBuiltName = "AsBuiltReport" - } - if ($Config.UserFolder.Path) { - $AsBuiltExportPath = Read-Host -Prompt "Enter the path to save the As Built Report configuration file [$($Config.UserFolder.Path)]" - if (($AsBuiltExportPath -like $null) -or ($AsBuiltExportPath -eq "")) { - $AsBuiltExportPath = $Config.UserFolder.Path - } - } elseif ($ReportConfigFilePath) { - $ReportConfigFolderPath = Split-Path -Path $ReportConfigFilePath - $AsBuiltExportPath = Read-Host -Prompt "Enter the path to save the As Built Report configuration file [$ReportConfigFolderPath]" - if (($AsBuiltExportPath -like $null) -or ($AsBuiltExportPath -eq "")) { - $AsBuiltExportPath = $ReportConfigFolderPath - } - } else { - $AsBuiltExportPath = Read-Host -Prompt "Enter the path to save the As Built Report configuration file [$($Home + $DirectorySeparatorChar)AsBuiltReport]" - if (($AsBuiltExportPath -like $null) -or ($AsBuiltExportPath -eq "")) { - $AsBuiltExportPath = $Home + $DirectorySeparatorChar + "AsBuiltReport" - } - } - if (-not (Test-Path -Path $AsBuiltExportPath)) { - Write-Verbose -Message "Creating As Built Report configuration folder '$AsBuiltExportPath'." - Try { - $Folder = New-Item -Path $AsBuiltExportPath -ItemType Directory -Force - } Catch { - Write-Error $_ - break - } - } - $Config.UserFolder = @{ - 'Path' = $AsBuiltExportPath - } - Write-Verbose -Message "Saving As Built Report configuration file '$($AsBuiltName).json' to path '$AsBuiltExportPath'." - $AsBuiltConfigPath = Join-Path -Path $AsBuiltExportPath -ChildPath "$AsBuiltName.json" - $Config | ConvertTo-Json | Out-File $AsBuiltConfigPath - } else { - Write-Verbose -Message "As Built Report configuration file not saved." - } - #endregion Save configuration - - # Print output to screen so that it can be captured to $Global:AsBuiltConfig variable in New-AsBuiltReport - $Config - - # Verbose Output - Write-Verbose -Message "Config.Report.Author = $ReportAuthor" - Write-Verbose -Message "Config.UserFolder.Path = $ReportConfigFolder" - foreach ($x in $Config.Company.Keys) { - Write-Verbose -Message "Config.Company.$x = $($Config.Company[$x])" - } - foreach ($x in $Config.Email.Keys) { - Write-Verbose -Message "Config.Email.$x = $($Config.Email[$x])" - } -}#End New-AsBuiltConfig Function \ No newline at end of file diff --git a/Src/Public/New-AsBuiltReport.ps1 b/Src/Public/New-AsBuiltReport.ps1 deleted file mode 100644 index f9f15ae..0000000 --- a/Src/Public/New-AsBuiltReport.ps1 +++ /dev/null @@ -1,502 +0,0 @@ -function New-AsBuiltReport { - <# - .SYNOPSIS - Documents the configuration of IT infrastructure in Word/HTML/Text formats using PScribo. - .DESCRIPTION - Documents the configuration of IT infrastructure in Word/HTML/Text formats using PScribo. - .PARAMETER Report - Specifies the type of report that will be generated. - .PARAMETER Target - Specifies the IP/FQDN of the system to connect. - Multiple targets may be specified, separated by a comma. - .PARAMETER Credential - Specifies the stored credential of the target system. - .PARAMETER Username - Specifies the username for the target system. - .PARAMETER Password - Specifies the password for the target system. - .PARAMETER Token - Specifies an API token to authenticate to the target system. - .PARAMETER MFA - Use multifactor authentication to authenticate to the target system. - .PARAMETER Format - Specifies the output format of the report. - The supported output formats are WORD, HTML & TEXT. - Multiple output formats may be specified, separated by a comma. - .PARAMETER Orientation - Sets the page orientation of the report to Portrait or Landscape. - By default, page orientation will be set to Portrait. - .PARAMETER StyleFilePath - Specifies the file path to a custom style .ps1 script for the report to use. - .PARAMETER OutputFolderPath - Specifies the folder path to save the report. - .PARAMETER Filename - Specifies a filename for the report. - .PARAMETER Timestamp - Specifies whether to append a timestamp string to the report filename. - By default, the timestamp string is not added to the report filename. - .PARAMETER EnableHealthCheck - Performs a health check of the target environment and highlights known issues within the report. - Not all reports may provide this functionality. - .PARAMETER SendEmail - Sends report to specified recipients as email attachments. - .PARAMETER AsBuiltConfigFilePath - Enter the full file path to the As Built Report configuration JSON file. - If this parameter is not specified, the user will be prompted for this configuration information on first - run, with the option to save the configuration to a file. - .PARAMETER ReportConfigFilePath - Enter the full file path to a report JSON configuration file - If this parameter is not specified, a default report configuration JSON is copied to the specifed user folder. - If this parameter is specified and the path to a JSON file is invalid, the script will terminate. - .EXAMPLE - New-AsBuiltReport -Report VMware.vSphere -Target 192.168.1.100 -Username admin -Password admin -Format HTML,Word -EnableHealthCheck -OutputFolderPath 'c:\scripts\' - - Creates a VMware vSphere As Built Report in HTML & Word formats. The document will highlight particular issues which exist within the environment. - The report will be saved to c:\scripts. - .EXAMPLE - $Creds = Get-Credential - New-AsBuiltReport -Report PureStorage.FlashArray -Target 192.168.1.100 -Credential $Creds -Format Text -Timestamp -OutputFolderPath 'c:\scripts\' - - Creates a Pure Storage FlashArray As Built Report in Text format and appends a timestamp to the filename. - Stored credentials are used to connect to the system. - The report will be saved to c:\scripts. - .EXAMPLE - New-AsBuiltReport -Report Rubrik.CDM -Target 192.168.1.100 -Token '123456789abcdefg' -Format HTML -OutputFolderPath 'c:\scripts\' - - Creates a Rubrik CDM As Built Report in HTML format. - An API token is used to connect to the system. - The report will be saved to c:\scripts. - .EXAMPLE - New-AsBuiltReport -Report Cisco.UCSManager -Target '192.168.1.100' -Username admin -Password admin -StyleFilePath '/Users/Tim/AsBuiltReport/Styles/ACME.ps1' -OutputFolderPath '/Users/Tim/scripts' - - Creates a Cisco UCS Manager As Built Report in default format (Word), using a custom style. - The report will be saved to '/Users/Tim/scripts'. - .EXAMPLE - New-AsBuiltReport -Report Nutanix.PrismElement -Target 192.168.1.100 -Username admin -Password admin -SendEmail -OutputFolderPath c:\scripts\ - - Creates a Nutanix Prism Element As Built Report in default format (Word). Report will be attached and sent via email. - The report will be saved to c:\scripts. - .EXAMPLE - New-AsBuiltReport -Report VMware.vSphere -Target 192.168.1.100 -Username admin -Password admin -Format HTML-AsBuiltConfigFilePath C:\scripts\asbuiltreport.json -OutputFolderPath c:\scripts\ - - Creates a VMware vSphere As Built Report in HTML format, using the configuration in the asbuiltreport.json file located in the C:\scripts\ folder. - The report will be saved to c:\scripts. - .LINK - https://github.com/AsBuiltReport/AsBuiltReport.Core - .LINK - https://www.asbuiltreport.com/user-guide/new-asbuiltreport/ - #> - - #region Script Parameters - [CmdletBinding( - PositionalBinding = $false, - DefaultParameterSetName = 'Credential' - )] - param ( - [Parameter( - Position = 0, - Mandatory = $true, - HelpMessage = 'Please specify which report type you wish to run.' - )] - [ValidateScript( { - $InstalledReportModules = Get-Module -Name "AsBuiltReport.*" -ListAvailable | Where-Object { $_.name -ne 'AsBuiltReport.Core' } | Sort-Object -Property Version -Descending | Select-Object -Unique - $ValidReports = foreach ($InstalledReportModule in $InstalledReportModules) { - $NameArray = $InstalledReportModule.Name.Split('.') - "$($NameArray[-2]).$($NameArray[-1])" - } - if ($ValidReports -contains $_) { - $true - } else { - throw "Invalid report type specified. Please use one of the following [$($ValidReports -Join ', ')]" - } - })] - [String] $Report, - - [Parameter( - Position = 1, - Mandatory = $true, - HelpMessage = 'Please provide the IP/FQDN of the system' - )] - [ValidateNotNullOrEmpty()] - [Alias('Cluster', 'Server', 'IP')] - [String[]] $Target, - [Parameter( - Position = 2, - Mandatory = $true, - HelpMessage = 'Please provide credentials to connect to the system', - ParameterSetName = 'Credential' - )] - [ValidateNotNullOrEmpty()] - [PSCredential] $Credential, - - [Parameter( - Position = 2, - Mandatory = $true, - HelpMessage = 'Please provide the username to connect to the target system', - ParameterSetName = 'UsernameAndPassword' - )] - [ValidateNotNullOrEmpty()] - [String] $Username, - - [Parameter( - Position = 3, - Mandatory = $false, - HelpMessage = 'Please provide the password to connect to the target system', - ParameterSetName = 'UsernameAndPassword' - )] - [ValidateNotNullOrEmpty()] - [String] $Password, - - [Parameter( - Position = 3, - Mandatory = $true, - HelpMessage = 'Please provide an API token to connect to the target system', - ParameterSetName = 'APIToken' - )] - [ValidateNotNullOrEmpty()] - [String] $Token, - - [Parameter( - Position = 3, - Mandatory = $true, - ParameterSetName = 'MFA' - )] - [ValidateNotNullOrEmpty()] - [Switch] $MFA, - - [Parameter( - Position = 4, - Mandatory = $false, - HelpMessage = 'Please provide the document output format' - )] - [ValidateNotNullOrEmpty()] - [ValidateSet('Word', 'HTML', 'Text')] - [Array] $Format = 'Word', - - [Parameter( - Mandatory = $false, - HelpMessage = 'Determines the document page orientation' - )] - [ValidateNotNullOrEmpty()] - [ValidateSet('Portrait', 'Landscape')] - [String] $Orientation = 'Portrait', - - [Parameter( - Mandatory = $true, - HelpMessage = 'Please provide the path to the document output file' - )] - [ValidateNotNullOrEmpty()] - [Alias('OutputPath')] - [String] $OutputFolderPath, - - [Parameter( - Mandatory = $false, - HelpMessage = 'Please provide the path to the custom style script' - )] - [ValidateNotNullOrEmpty()] - [Alias('StylePath')] - [String] $StyleFilePath, - - [Parameter( - Mandatory = $false, - HelpMessage = 'Provide the file path to an existing report JSON Configuration file' - )] - [ValidateNotNullOrEmpty()] - [Alias('ReportConfigPath')] - [String] $ReportConfigFilePath, - - [Parameter( - Mandatory = $false, - HelpMessage = 'Provide the file path to an existing As Built JSON Configuration file' - )] - [ValidateNotNullOrEmpty()] - [Alias('AsBuiltConfigPath')] - [String] $AsBuiltConfigFilePath, - - [Parameter( - Mandatory = $false, - HelpMessage = 'Specify the As Built Report filename' - )] - [ValidateNotNullOrEmpty()] - [String] $Filename, - - [Parameter( - Mandatory = $false, - HelpMessage = 'Specify whether to append a timestamp to the document filename' - )] - [Switch] $Timestamp = $false, - - [Parameter( - Mandatory = $false, - HelpMessage = 'Specify whether to highlight any configuration issues within the document' - )] - [Switch] $EnableHealthCheck = $false, - - [Parameter( - Mandatory = $false, - HelpMessage = 'Specify whether to send report via Email' - )] - [Switch] $SendEmail = $false - ) - #endregion Script Parameters - - $DirectorySeparatorChar = [System.IO.Path]::DirectorySeparatorChar - - try { - - if ($psISE) { - Write-Error -Message "AsBuiltReport cannot be run from Windows PowerShell ISE. Please use a PowerShell command window instead." - break - } - - # If Username and Password parameters used, convert specified Password to secure string and store in $Credential - if ($Username) { - if (-not $Password) { - # If the Password parameter is not provided, prompt for it securely - $SecurePassword = Read-Host "Password for user $Username" -AsSecureString - } else { - # If the Password parameter is provided, convert it to secure string - $SecurePassword = ConvertTo-SecureString $Password -AsPlainText -Force - } - $Credential = New-Object System.Management.Automation.PSCredential ($Username, $SecurePassword) - } - - if (-not (Test-Path $OutputFolderPath)) { - Write-Error "OutputFolderPath '$OutputFolderPath' is not a valid folder path." - break - } - #region Variable config - - # Import the AsBuiltReport JSON configuration file - # If no path was specified, or the specified file doesn't exist, call New-AsBuiltConfig to walk the user through the menu prompt to create a config JSON - if ($AsBuiltConfigFilePath) { - if (Test-Path -Path $AsBuiltConfigFilePath) { - $Global:AsBuiltConfig = Get-Content -Path $AsBuiltConfigFilePath | ConvertFrom-Json - # Verbose Output for As Built Report configuration - Write-Verbose -Message "Loading As Built Report configuration from '$AsBuiltConfigFilePath'." - } else { - Write-Error "Could not find As Built Report configuration in path '$AsBuiltConfigFilePath'." - break - } - } else { - Write-Verbose -Message "Generating new As Built Report configuration" - $Global:AsBuiltConfig = New-AsBuiltConfig - } - - # Set ReportConfigFilePath as Global scope for use in New-AsBuiltConfig - if ($ReportConfigFilePath) { - $Global:ReportConfigFilePath = $ReportConfigFilePath - } - - # Set $OutputFolderPath as Global scope - if ($OutputFolderPath) { - $Global:OutputFolderPath = $OutputFolderPath - } - - # If StyleFilePath was specified, ensure the file provided in the path exists, otherwise exit with error - if ($StyleFilePath) { - if (-not (Test-Path -Path $StyleFilePath)) { - Write-Error "Could not find report style script in path '$StyleFilePath'." - break - } - } - - # Report Module Information - $Global:Report = $Report - $ReportModuleName = "AsBuiltReport.$Report" - $CoreModulePath = (Get-Module -Name 'AsBuiltReport.Core' -ListAvailable | Sort-Object -Property Version -Descending | Select-Object -First 1).ModuleBase - $ReportModulePath = (Get-Module -Name $ReportModuleName -ListAvailable | Sort-Object -Property Version -Descending | Select-Object -First 1).ModuleBase - - if ($ReportConfigFilePath) { - # If ReportConfigFilePath was specified, ensure the file provided in the path exists, otherwise exit with error - if (-not (Test-Path -Path $ReportConfigFilePath)) { - Write-Error "Could not find $ReportModuleName report configuration file in path '$ReportConfigFilePath'." - break - } else { - #Import the Report Configuration in to a variable - Write-Verbose -Message "Loading $ReportModuleName report configuration file from path '$ReportConfigFilePath'." - $Global:ReportConfig = Get-Content -Path $ReportConfigFilePath | ConvertFrom-Json - } - } else { - # If a report config hasn't been provided, check for the existance of the default JSON in the paths the user specified in base config - $ReportConfigFilePath = $ReportModulePath + $DirectorySeparatorChar + "$($ReportModuleName).json" - - if (Test-Path -Path $ReportConfigFilePath) { - Write-Verbose -Message "Loading report configuration file from path '$ReportConfigFilePath'." - $Global:ReportConfig = Get-Content -Path $ReportConfigFilePath | ConvertFrom-Json - } else { - Write-Error "Report configuration file not found in module path '$ReportModulePath'." - break - }#End if test-path - }#End if ReportConfigFilePath - - # If Filename parameter is not specified, set filename to the report name - if (-not $Filename) { - $FileName = $ReportConfig.Report.Name - } - # If Timestamp parameter is specified, add the timestamp to the report filename - if ($Timestamp) { - $FileName = $Filename + " - " + (Get-Date -Format 'yyyy-MM-dd_HH.mm.ss') - } - Write-Verbose -Message "Setting report filename to '$FileName'." - - # If the EnableHealthCheck parameter has been specified, set the global healthcheck variable so report scripts can reference the health checks - if ($EnableHealthCheck) { - $Global:Healthcheck = $ReportConfig.HealthCheck - } - - # Set Global scope for Orientation parameter - $Global:Orientation = $Orientation - - #endregion Variable config - - #region Email Server Authentication - # If Email Server Authentication is required, prompt user for credentials - if ($SendEmail -and $AsBuiltConfig.Email.Credentials) { - Clear-Host - Write-Host '---------------------------------------------' -ForegroundColor Cyan - Write-Host ' < Email Server Credentials > ' -ForegroundColor Cyan - Write-Host '---------------------------------------------' -ForegroundColor Cyan - $MailCredentials = Get-Credential -Message "Please enter the credentials for $($AsBuiltConfig.Email.Server)" - Clear-Host - } - #endregion Email Server Authentication - - # Check installed module version - Try { - $InstalledVersion = Get-Module -ListAvailable -Name AsBuiltReport.Core -ErrorAction SilentlyContinue | Sort-Object -Property Version -Descending | Select-Object -First 1 -ExpandProperty Version - - if ($InstalledVersion) { - Write-PScriboMessage -Plugin "Module" -IsWarning "AsBuiltReport.Core $($InstalledVersion.ToString()) is currently installed." - $LatestVersion = Find-Module -Name AsBuiltReport.Core -Repository PSGallery -ErrorAction SilentlyContinue | Select-Object -ExpandProperty Version - if ($LatestVersion -gt $InstalledVersion) { - Write-PScriboMessage -Plugin "Module" -IsWarning "AsBuiltReport.Core $($LatestVersion.ToString()) is available." - Write-PScriboMessage -Plugin "Module" -IsWarning "Run 'Update-Module -Name AsBuiltReport.Core -Force' to install the latest version." - } - } - } Catch { - Write-PscriboMessage -Plugin "Module" -IsWarning $_.Exception.Message - } - - #region Generate PScribo document - # if Verbose has been passed - if ($PSCmdlet.MyInvocation.BoundParameters["Verbose"].IsPresent) { - $AsBuiltReport = Document $FileName -Verbose { - Write-PScriboMessage "Please wait while the $($Report.Replace("."," ")) As Built Report is being generated." - # Set Document Style - if ($StyleFilePath) { - Write-PScriboMessage "Executing report style script from path '$StyleFilePath'." - . $StyleFilePath - } else { - $StyleFilePath = $CoreModulePath + $DirectorySeparatorChar + 'AsBuiltReport.Core.Style.ps1' - Write-PScriboMessage "Executing report style script from path '$($StyleFilePath)'." - . $StyleFilePath - } - # If Credential has been passed or previously created via Username/Password - if ($Credential) { - & "Invoke-$($ReportModuleName)" -Target $Target -Credential $Credential -Verbose - } - elseif ($Token) { - & "Invoke-$($ReportModuleName)" -Target $Target -Token $Token -Verbose - } - elseif ($MFA) { - Write-PScriboMessage -Plugin "MFA" -IsWarning "MFA is enabled, please check for MFA authentication windows to generate your report." - & "Invoke-$($ReportModuleName)" -Target $Target -MFA -Verbose - } - } - } else { - $AsBuiltReport = Document $FileName { - Write-Host "Please wait while the $($Report.Replace("."," ")) As Built Report is being generated." -ForegroundColor Green - if ($MFA) { - Write-Host "MFA is enabled, please check for MFA authentication windows to generate your report." -ForegroundColor Yellow - } - # Set Document Style - if ($StyleFilePath) { - Write-PScriboMessage "Executing report style script from path '$StyleFilePath'." - . $StyleFilePath - } else { - $StyleFilePath = $CoreModulePath + $DirectorySeparatorChar + 'AsBuiltReport.Core.Style.ps1' - Write-PScriboMessage "Executing report style script from path '$($StyleFilePath)'." - . $StyleFilePath - } - # If Credential has been passed or previously created via Username/Password - if ($Credential) { - & "Invoke-$($ReportModuleName)" -Target $Target -Credential $Credential - } - elseif ($Token) { - & "Invoke-$($ReportModuleName)" -Target $Target -Token $Token - } - elseif ($MFA) { - & "Invoke-$($ReportModuleName)" -Target $Target -MFA - } - } - } - Try { - $Document = $AsBuiltReport | Export-Document -Path $OutputFolderPath -Format $Format -Options @{ TextWidth = 240 } -PassThru - Write-Output "$($Report.Replace("."," ")) As Built Report '$FileName' has been saved to '$OutputFolderPath'." - } catch { - $Err = $_ - Write-Error $Err - } - #endregion Generate PScribo document - - #region Send-Email - if ($SendEmail) { - $EmailArguments = @{ - Attachments = $Document - To = $AsBuiltConfig.Email.To - From = $AsBuiltConfig.Email.From - Subject = $ReportConfig.Report.Name - Body = $AsBuiltConfig.Email.Body - SmtpServer = $AsBuiltConfig.Email.Server - Port = $AsBuiltConfig.Email.Port - UseSSL = $AsBuiltConfig.Email.UseSSL - } - - if ($AsBuiltConfig.Email.Credentials) { - # Send the report via SMTP using SSL - Send-MailMessage @EmailArguments -Credential $MailCredentials - } else { - # Send the report via SMTP - Send-MailMessage @EmailArguments - } - } - #endregion Send-Email - - #region Globals cleanup - Remove-Variable -Name AsBuiltConfig -Scope Global - Remove-Variable -Name ReportConfig -Scope Global - Remove-Variable -Name Report -Scope Global - Remove-Variable -Name Orientation -Scope Global - if ($ReportConfigFilePath) { - Remove-Variable -Name ReportConfigFilePath - } - if ($Healthcheck) { - Remove-Variable -Name Healthcheck -Scope Global - } - #endregion Globals cleanup - - } catch { - Write-Error $_ - } -} - -Register-ArgumentCompleter -CommandName 'New-AsBuiltReport' -ParameterName 'Report' -ScriptBlock { - param ( - $commandName, - $parameterName, - $wordToComplete, - $commandAst, - $fakeBoundParameter - ) - - $InstalledReportModules = Get-Module -Name "AsBuiltReport.*" -ListAvailable | Where-Object { $_.name -ne 'AsBuiltReport.Core' } | Sort-Object -Property Version -Descending | Select-Object -Unique - $ValidReports = foreach ($InstalledReportModule in $InstalledReportModules) { - $NameArray = $InstalledReportModule.Name.Split('.') - "$($NameArray[-2]).$($NameArray[-1])" - } - - $ValidReports | Where-Object { $_ -like "$wordToComplete*" } | ForEach-Object { - [System.Management.Automation.CompletionResult]::new($_, $_, 'ParameterValue', $_) - } -} diff --git a/TESTING.md b/TESTING.md new file mode 100644 index 0000000..7d7392d --- /dev/null +++ b/TESTING.md @@ -0,0 +1,409 @@ +# AsBuiltReport.Core Testing Guide + +This document provides comprehensive information about the testing infrastructure for the AsBuiltReport.Core PowerShell module. + +## Overview + +The AsBuiltReport.Core module includes a complete testing suite powered by Pester 5, covering: +- **Module manifest and structure validation** +- **Unit tests** for all public functions +- **Integration tests** for module loading and dependencies +- **Code quality tests** for PowerShell best practices +- **Automated CI/CD pipeline** for continuous testing + +## Quick Start + +### Prerequisites + +Ensure you have PowerShell 7.4 or later installed: +```powershell +$PSVersionTable.PSVersion +``` + +### Install Required Modules + +```powershell +# Install Pester 5+ +Install-Module -Name Pester -MinimumVersion 5.0.0 -Force + +# Install PSScriptAnalyzer for code quality checks +Install-Module -Name PSScriptAnalyzer -Force + +# Install PScribo (required by AsBuiltReport.Core) +Install-Module -Name PScribo -MinimumVersion 0.11.1 -Force +``` + +### Run Tests + +The easiest way to run tests is using the included helper script: + +```powershell +# Run all tests +.\Tests\Invoke-Tests.ps1 + +# Run only unit tests +.\Tests\Invoke-Tests.ps1 -TestType Unit + +# Run with code coverage +.\Tests\Invoke-Tests.ps1 -CodeCoverage -ShowCodeCoverage + +# Run with XML output for CI/CD +.\Tests\Invoke-Tests.ps1 -OutputFormat NUnitXml +``` + +## Test Structure + +``` +Tests/ +├── AsBuiltReport.Core.Tests.ps1 # Module-level tests +├── Unit/ # Unit tests for individual functions +│ ├── New-AsBuiltReport.Tests.ps1 +│ ├── New-AsBuiltConfig.Tests.ps1 +│ └── New-AsBuiltReportConfig.Tests.ps1 +├── Integration/ # Integration tests +│ └── ModuleImport.Tests.ps1 +├── Quality/ # Code quality tests +│ └── CodeQuality.Tests.ps1 +└── README.md # Detailed test documentation +``` + +## Test Categories + +### 1. Module Tests (`AsBuiltReport.Core.Tests.ps1`) + +Tests the overall module structure and configuration: +- ✓ Module manifest validation +- ✓ Correct GUID and version +- ✓ Required dependencies (PScribo) +- ✓ Exported functions +- ✓ Module metadata (tags, URIs, etc.) +- ✓ File structure (Src/Public/Private folders) +- ✓ Language support (en-US and other locales) + +### 2. Unit Tests (`Unit/`) + +Tests individual functions in isolation: + +#### New-AsBuiltReport Tests +- ✓ Parameter validation and types +- ✓ Parameter aliases (Target/Server/IP, etc.) +- ✓ Multiple parameter sets (Credential, Token, InteractiveAuth) +- ✓ Format validation (Word, HTML, Text) +- ✓ Orientation validation (Portrait, Landscape) +- ✓ Help documentation completeness +- ✓ Argument completers +- ✓ Error handling for invalid inputs + +#### New-AsBuiltReportConfig Tests +- ✓ Mandatory parameters +- ✓ Parameter aliases +- ✓ Folder path validation +- ✓ Force/Overwrite functionality +- ✓ Help documentation +- ✓ Error handling + +#### New-AsBuiltConfig Tests +- ✓ Parameter structure +- ✓ CmdletBinding verification +- ✓ Help documentation +- ✓ Output type validation + +### 3. Integration Tests (`Integration/`) + +Tests module integration and dependencies: +- ✓ Module imports without errors +- ✓ All public functions load correctly +- ✓ Private functions remain private +- ✓ PScribo dependency loads +- ✓ Version compatibility +- ✓ Language file loading +- ✓ Metadata validation + +### 4. Quality Tests (`Quality/`) + +Tests code quality and best practices: +- ✓ PowerShell syntax validation (PSParser) +- ✓ AST parsing validation +- ✓ File encoding (UTF-8) +- ✓ Comment-based help for all public functions +- ✓ CmdletBinding on all functions +- ✓ Approved PowerShell verbs +- ✓ Manifest completeness +- ✓ No wildcard exports +- ✓ Documentation files (README, CHANGELOG, LICENSE) +- ✓ Language file consistency across cultures + +## CI/CD Pipeline + +### Automated Testing Workflow + +The module includes a dedicated GitHub Actions workflow (`.github/workflows/Pester.yml`) that: + +1. **Runs on Multiple Events** + - Push to main/dev/master branches + - Pull requests to main/dev/master + - Manual workflow dispatch + +2. **Platform** + - Windows Server (latest) + +3. **Test Jobs** + - **Test Job**: Runs `Tests\Invoke-Tests.ps1` with code coverage + - **Analyze Job**: Runs PSScriptAnalyzer for code quality + +4. **Artifacts** + - Test results (NUnit XML) + - Code coverage reports (JaCoCo XML) + +### Workflow Features + +- ✅ Automatic module dependency installation +- ✅ Code coverage analysis +- ✅ PSScriptAnalyzer static analysis +- ✅ Uses the same test script as local development + +### Pipeline Status Badges + +Add these to your README.md: + +```markdown +![Tests](https://github.com/AsBuiltReport/AsBuiltReport.Core/workflows/Pester%20Tests/badge.svg) +[![codecov](https://codecov.io/gh/AsBuiltReport/AsBuiltReport.Core/branch/master/graph/badge.svg)](https://codecov.io/gh/AsBuiltReport/AsBuiltReport.Core) +``` + +## Running Tests Manually + +### Using Invoke-Pester Directly + +```powershell +# Basic test execution +Invoke-Pester -Path ./Tests + +# Detailed output +Invoke-Pester -Path ./Tests -Output Detailed + +# Specific test file +Invoke-Pester -Path ./Tests/Unit/New-AsBuiltReport.Tests.ps1 + +# With code coverage +$Config = New-PesterConfiguration +$Config.Run.Path = './Tests' +$Config.CodeCoverage.Enabled = $true +$Config.CodeCoverage.Path = './AsBuiltReport.Core/**/*.ps1' +$Config.Output.Verbosity = 'Detailed' +Invoke-Pester -Configuration $Config +``` + +### Using the Helper Script + +```powershell +# Run all tests with detailed output +.\Tests\Invoke-Tests.ps1 + +# Run specific test category +.\Tests\Invoke-Tests.ps1 -TestType Unit +.\Tests\Invoke-Tests.ps1 -TestType Integration +.\Tests\Invoke-Tests.ps1 -TestType Quality + +# Enable code coverage analysis +.\Tests\Invoke-Tests.ps1 -CodeCoverage -ShowCodeCoverage + +# Export results to XML +.\Tests\Invoke-Tests.ps1 -OutputFormat NUnitXml +.\Tests\Invoke-Tests.ps1 -OutputFormat JUnitXml + +# Combine options +.\Tests\Invoke-Tests.ps1 -TestType Unit -CodeCoverage -ShowCodeCoverage -OutputFormat NUnitXml +``` + +## Test Development Guidelines + +### Writing New Tests + +When adding new tests, follow these best practices: + +1. **Use Pester 5 Syntax** + ```powershell + BeforeAll { + # Setup code + } + + Describe 'Feature Name' { + Context 'Specific Scenario' { + It 'Should do something specific' { + # Test code + $Result | Should -Be $Expected + } + } + } + + AfterAll { + # Cleanup code + } + ``` + +2. **Organize Tests Logically** + - Place unit tests in `Tests/Unit/` + - Place integration tests in `Tests/Integration/` + - Place quality tests in `Tests/Quality/` + +3. **Use Descriptive Names** + ```powershell + # Good + It 'Should throw error when OutputFolderPath does not exist' + + # Bad + It 'Test 1' + ``` + +4. **Test Both Positive and Negative Cases** + ```powershell + It 'Should accept valid format parameter' { + # Positive test + } + + It 'Should reject invalid format parameter' { + # Negative test + } + ``` + +5. **Clean Up After Tests** + ```powershell + AfterAll { + Remove-Module -Name 'AsBuiltReport.Core' -Force -ErrorAction SilentlyContinue + if (Test-Path $TestFolder) { + Remove-Item -Path $TestFolder -Recurse -Force + } + } + ``` + +6. **Mock External Dependencies** + ```powershell + BeforeAll { + Mock -CommandName 'Get-ExternalData' -MockWith { + return @{ Status = 'Success' } + } + } + ``` + +### Test Coverage Goals + +- **Overall Coverage**: Target 80%+ code coverage +- **Public Functions**: 100% parameter validation coverage +- **Critical Paths**: 100% coverage for core functionality +- **Error Handling**: All error paths should be tested + +## Troubleshooting + +### Common Issues + +#### Tests Fail with "Module Not Found" + +**Solution**: Ensure the module path is correct in your test files: +```powershell +$ModulePath = Join-Path -Path $PSScriptRoot -ChildPath '..\..\AsBuiltReport.Core\AsBuiltReport.Core.psd1' +Import-Module $ModulePath -Force +``` + +#### Code Coverage Shows 0% + +**Solution**: Verify the coverage path includes your module files: +```powershell +$Config.CodeCoverage.Path = './AsBuiltReport.Core/**/*.ps1' +``` + +#### PSScriptAnalyzer Errors + +**Solution**: Run PSScriptAnalyzer locally to identify issues: +```powershell +Invoke-ScriptAnalyzer -Path ./AsBuiltReport.Core -Recurse +``` + +#### Tests Pass Locally But Fail in CI + +**Possible Causes**: +- PowerShell version differences +- Module dependencies not installed +- Platform-specific code (Windows vs Linux) +- File path case sensitivity (Linux/macOS) + +**Solution**: +- Check the CI logs for specific errors +- Test on multiple platforms locally using Docker +- Ensure all dependencies are in the workflow YAML + +### Debug Failed Tests + +```powershell +# Run specific test with detailed output +Invoke-Pester -Path ./Tests/Unit/New-AsBuiltReport.Tests.ps1 -Output Detailed + +# Run with debug output +$DebugPreference = 'Continue' +Invoke-Pester -Path ./Tests/Unit/New-AsBuiltReport.Tests.ps1 + +# Run single test +Invoke-Pester -Path ./Tests/Unit/New-AsBuiltReport.Tests.ps1 -FullNameFilter '*Should have Report parameter*' +``` + +## Performance Considerations + +### Test Execution Time + +- **Unit Tests**: ~10-30 seconds +- **Integration Tests**: ~5-10 seconds +- **Quality Tests**: ~30-60 seconds +- **Total Suite**: ~1-2 minutes + +### Optimization Tips + +1. **Use `BeforeAll` for expensive setup operations** +2. **Mock external calls to avoid network delays** +3. **Clean up resources in `AfterAll` instead of `AfterEach`** +4. **Use `-Skip` for tests that don't apply to current environment** + +## Best Practices + +### Do's ✅ +- ✅ Write tests before fixing bugs (TDD) +- ✅ Test edge cases and boundary conditions +- ✅ Use meaningful test descriptions +- ✅ Keep tests independent and isolated +- ✅ Clean up resources after tests +- ✅ Update tests when changing functionality +- ✅ Aim for high code coverage + +### Don'ts ❌ +- ❌ Don't test PowerShell itself +- ❌ Don't make tests dependent on each other +- ❌ Don't use hardcoded file paths +- ❌ Don't skip cleanup steps +- ❌ Don't ignore failing tests +- ❌ Don't commit test artifacts (XML files, coverage reports) + +## Resources + +### Documentation +- [Pester Documentation](https://pester.dev/) +- [Pester Quick Start](https://pester.dev/docs/quick-start) +- [PSScriptAnalyzer Rules](https://github.com/PowerShell/PSScriptAnalyzer) +- [PowerShell Best Practices](https://learn.microsoft.com/en-us/powershell/scripting/developer/cmdlet/strongly-encouraged-development-guidelines) + +### GitHub Actions +- [GitHub Actions Documentation](https://docs.github.com/en/actions) +- [PowerShell in GitHub Actions](https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-powershell) + +### Code Coverage +- [Codecov Documentation](https://docs.codecov.com/) +- [JaCoCo Format](https://www.jacoco.org/jacoco/trunk/doc/) + +## Support + +For issues, questions, or contributions: +- **Issues**: [GitHub Issues](https://github.com/AsBuiltReport/AsBuiltReport.Core/issues) +- **Discussions**: [GitHub Discussions](https://github.com/AsBuiltReport/AsBuiltReport.Core/discussions) +- **Documentation**: [AsBuiltReport.com](https://www.asbuiltreport.com/) + +## License + +This testing infrastructure is part of the AsBuiltReport.Core project and follows the same license. diff --git a/Tests/AsBuiltReport.Core.Tests.ps1 b/Tests/AsBuiltReport.Core.Tests.ps1 new file mode 100644 index 0000000..6b5c837 --- /dev/null +++ b/Tests/AsBuiltReport.Core.Tests.ps1 @@ -0,0 +1,251 @@ +BeforeAll { + # Import the module + $ModulePath = Join-Path -Path $PSScriptRoot -ChildPath '..\AsBuiltReport.Core\AsBuiltReport.Core.psd1' + Import-Module $ModulePath -Force +} + +Describe 'AsBuiltReport.Core Module Tests' { + Context 'Module Manifest' { + BeforeAll { + $ManifestPath = Join-Path -Path $PSScriptRoot -ChildPath '..\AsBuiltReport.Core\AsBuiltReport.Core.psd1' + $Manifest = Test-ModuleManifest -Path $ManifestPath -ErrorAction Stop + } + + It 'Should have a valid module manifest' { + $Manifest | Should -Not -BeNullOrEmpty + } + + It 'Should have the correct module name' { + $Manifest.Name | Should -Be 'AsBuiltReport.Core' + } + + It 'Should have a valid GUID' { + $Manifest.Guid | Should -Be '0f1094c4-c6b1-495c-8cdd-9331f67f9f6f' + } + + It 'Should have a valid version' { + $Manifest.Version | Should -Not -BeNullOrEmpty + $Manifest.Version.GetType().Name | Should -Be 'Version' + } + + It 'Should have a valid author' { + $Manifest.Author | Should -Not -BeNullOrEmpty + } + + It 'Should have a valid description' { + $Manifest.Description | Should -Not -BeNullOrEmpty + } + + It 'Should require PScribo module' { + $Manifest.RequiredModules | Should -Not -BeNullOrEmpty + $Manifest.RequiredModules.Name | Should -Contain 'PScribo' + } + + It 'Should export the correct functions' { + $Manifest.ExportedFunctions.Keys | Should -Contain 'New-AsBuiltReport' + $Manifest.ExportedFunctions.Keys | Should -Contain 'New-AsBuiltConfig' + $Manifest.ExportedFunctions.Keys | Should -Contain 'New-AsBuiltReportConfig' + } + + It 'Should have valid tags' { + $Manifest.Tags | Should -Contain 'AsBuiltReport' + $Manifest.Tags | Should -Contain 'Report' + $Manifest.Tags | Should -Contain 'PScribo' + } + + It 'Should have a valid project URI' { + $Manifest.ProjectUri | Should -Not -BeNullOrEmpty + $Manifest.ProjectUri.ToString() | Should -Match '^https?://' + } + + It 'Should have a valid license URI' { + $Manifest.LicenseUri | Should -Not -BeNullOrEmpty + $Manifest.LicenseUri.ToString() | Should -Match '^https?://' + } + } + + Context 'Module Structure' { + It 'Should have a valid root module file' { + $RootModulePath = Join-Path -Path $PSScriptRoot -ChildPath '..\AsBuiltReport.Core\AsBuiltReport.Core.psm1' + Test-Path $RootModulePath | Should -Be $true + } + + It 'Should have a Src folder' { + $SrcPath = Join-Path -Path $PSScriptRoot -ChildPath '..\AsBuiltReport.Core\Src' + Test-Path $SrcPath | Should -Be $true + } + + It 'Should have a Public functions folder' { + $PublicPath = Join-Path -Path $PSScriptRoot -ChildPath '..\AsBuiltReport.Core\Src\Public' + Test-Path $PublicPath | Should -Be $true + } + + It 'Should have a Private functions folder' { + $PrivatePath = Join-Path -Path $PSScriptRoot -ChildPath '..\AsBuiltReport.Core\Src\Private' + Test-Path $PrivatePath | Should -Be $true + } + + It 'Should have a Language folder' { + $LanguagePath = Join-Path -Path $PSScriptRoot -ChildPath '..\AsBuiltReport.Core\Language' + Test-Path $LanguagePath | Should -Be $true + } + + It 'Should have en-US language files' { + $EnUSPath = Join-Path -Path $PSScriptRoot -ChildPath '..\AsBuiltReport.Core\Language\en-US' + Test-Path $EnUSPath | Should -Be $true + } + } + + Context 'Public Functions' { + It 'Should export New-AsBuiltReport function' { + Get-Command -Name 'New-AsBuiltReport' -Module 'AsBuiltReport.Core' -ErrorAction SilentlyContinue | Should -Not -BeNullOrEmpty + } + + It 'Should export New-AsBuiltConfig function' { + Get-Command -Name 'New-AsBuiltConfig' -Module 'AsBuiltReport.Core' -ErrorAction SilentlyContinue | Should -Not -BeNullOrEmpty + } + + It 'Should export New-AsBuiltReportConfig function' { + Get-Command -Name 'New-AsBuiltReportConfig' -Module 'AsBuiltReport.Core' -ErrorAction SilentlyContinue | Should -Not -BeNullOrEmpty + } + + It 'Should have exactly 3 exported functions' { + $ExportedFunctions = Get-Command -Module 'AsBuiltReport.Core' -CommandType Function + # Note: Get-RequiredModule and Write-ReportModuleInfo are made globally available for report modules + # but they are not formally exported functions, they appear in Get-Command output + # Filter to only count the officially exported public functions + $PublicFunctions = $ExportedFunctions | Where-Object { + $_.Name -in @('New-AsBuiltReport', 'New-AsBuiltConfig', 'New-AsBuiltReportConfig') + } + $PublicFunctions.Count | Should -Be 3 + } + } + + Context 'Function Parameter Validation' { + BeforeAll { + $NewAsBuiltReportCommand = Get-Command -Name 'New-AsBuiltReport' + $NewAsBuiltReportConfigCommand = Get-Command -Name 'New-AsBuiltReportConfig' + } + + It 'New-AsBuiltReport should have Report parameter' { + $NewAsBuiltReportCommand.Parameters.Keys | Should -Contain 'Report' + } + + It 'New-AsBuiltReport should have Target parameter' { + $NewAsBuiltReportCommand.Parameters.Keys | Should -Contain 'Target' + } + + It 'New-AsBuiltReport should have Format parameter' { + $NewAsBuiltReportCommand.Parameters.Keys | Should -Contain 'Format' + } + + It 'New-AsBuiltReport should have OutputFolderPath parameter' { + $NewAsBuiltReportCommand.Parameters.Keys | Should -Contain 'OutputFolderPath' + } + + It 'New-AsBuiltReport should have Credential parameter' { + $NewAsBuiltReportCommand.Parameters.Keys | Should -Contain 'Credential' + } + + It 'New-AsBuiltReport Format parameter should accept Word, HTML, and Text' { + $FormatParam = $NewAsBuiltReportCommand.Parameters['Format'] + $ValidateSetAttribute = $FormatParam.Attributes | Where-Object { $_ -is [System.Management.Automation.ValidateSetAttribute] } + $ValidateSetAttribute.ValidValues | Should -Contain 'Word' + $ValidateSetAttribute.ValidValues | Should -Contain 'HTML' + $ValidateSetAttribute.ValidValues | Should -Contain 'Text' + } + + It 'New-AsBuiltReportConfig should have Report parameter' { + $NewAsBuiltReportConfigCommand.Parameters.Keys | Should -Contain 'Report' + } + + It 'New-AsBuiltReportConfig should have FolderPath parameter' { + $NewAsBuiltReportConfigCommand.Parameters.Keys | Should -Contain 'FolderPath' + } + } + + Context 'Help Content' { + It 'New-AsBuiltReport should have help content' { + $Help = Get-Help -Name 'New-AsBuiltReport' -ErrorAction SilentlyContinue + $Help | Should -Not -BeNullOrEmpty + $Help.Synopsis | Should -Not -BeNullOrEmpty + } + + It 'New-AsBuiltConfig should have help content' { + $Help = Get-Help -Name 'New-AsBuiltConfig' -ErrorAction SilentlyContinue + $Help | Should -Not -BeNullOrEmpty + $Help.Synopsis | Should -Not -BeNullOrEmpty + } + + It 'New-AsBuiltReportConfig should have help content' { + $Help = Get-Help -Name 'New-AsBuiltReportConfig' -ErrorAction SilentlyContinue + $Help | Should -Not -BeNullOrEmpty + $Help.Synopsis | Should -Not -BeNullOrEmpty + } + + It 'New-AsBuiltReport should have description' { + $Help = Get-Help -Name 'New-AsBuiltReport' -ErrorAction SilentlyContinue + $Help.Description | Should -Not -BeNullOrEmpty + } + + It 'New-AsBuiltConfig should have description' { + $Help = Get-Help -Name 'New-AsBuiltConfig' -ErrorAction SilentlyContinue + $Help.Description | Should -Not -BeNullOrEmpty + } + + It 'New-AsBuiltReportConfig should have description' { + $Help = Get-Help -Name 'New-AsBuiltReportConfig' -ErrorAction SilentlyContinue + $Help.Description | Should -Not -BeNullOrEmpty + } + + It 'New-AsBuiltReport should have examples' { + $Help = Get-Help -Name 'New-AsBuiltReport' -ErrorAction SilentlyContinue + $Help.Examples | Should -Not -BeNullOrEmpty + } + + It 'New-AsBuiltConfig should have examples' { + $Help = Get-Help -Name 'New-AsBuiltConfig' -ErrorAction SilentlyContinue + $Help.Examples | Should -Not -BeNullOrEmpty + } + + It 'New-AsBuiltReportConfig should have examples' { + $Help = Get-Help -Name 'New-AsBuiltReportConfig' -ErrorAction SilentlyContinue + $Help.Examples | Should -Not -BeNullOrEmpty + } + } +} + +Describe 'Module File Syntax and Quality' { + Context 'PowerShell Script Files' { + It 'Should have valid PowerShell syntax in all script files' { + $ModuleRoot = Join-Path -Path $PSScriptRoot -ChildPath '..\AsBuiltReport.Core' + $ScriptFiles = Get-ChildItem -Path $ModuleRoot -Include '*.ps1', '*.psm1' -Recurse + + foreach ($File in $ScriptFiles) { + $FileContent = Get-Content -Path $File.FullName -Raw -ErrorAction Stop + $Errors = $null + $null = [System.Management.Automation.PSParser]::Tokenize($FileContent, [ref]$Errors) + $Errors.Count | Should -Be 0 -Because "File $($File.Name) should have no syntax errors" + } + } + } + + Context 'Language Files' { + It 'Should have valid PowerShell localization data files' { + $LanguagePath = Join-Path -Path $PSScriptRoot -ChildPath '..\AsBuiltReport.Core\Language' + $LanguageFiles = Get-ChildItem -Path $LanguagePath -Include '*.psd1' -Recurse -ErrorAction SilentlyContinue + + foreach ($File in $LanguageFiles) { + # All .psd1 files in Language folder use ConvertFrom-StringData and should be loaded with Import-LocalizedData + { + $null = Import-LocalizedData -BaseDirectory $File.Directory.FullName -FileName $File.Name -ErrorAction Stop + } | Should -Not -Throw -Because "Localization file $($File.FullName) should be valid" + } + } + } +} + +AfterAll { + # Clean up + Remove-Module -Name 'AsBuiltReport.Core' -Force -ErrorAction SilentlyContinue +} diff --git a/Tests/Integration/ModuleImport.Tests.ps1 b/Tests/Integration/ModuleImport.Tests.ps1 new file mode 100644 index 0000000..ee6b92d --- /dev/null +++ b/Tests/Integration/ModuleImport.Tests.ps1 @@ -0,0 +1,121 @@ +BeforeAll { + # Remove module if already loaded + Remove-Module -Name 'AsBuiltReport.Core' -Force -ErrorAction SilentlyContinue +} + +Describe 'AsBuiltReport.Core Module Import Integration Tests' { + Context 'Module Import' { + It 'Should import the module without errors' { + $ModulePath = Join-Path -Path $PSScriptRoot -ChildPath '..\..\AsBuiltReport.Core\AsBuiltReport.Core.psd1' + { Import-Module $ModulePath -Force -ErrorAction Stop } | Should -Not -Throw + } + + It 'Should have the module loaded' { + Get-Module -Name 'AsBuiltReport.Core' | Should -Not -BeNullOrEmpty + } + + It 'Should load all public functions' { + $Commands = Get-Command -Module 'AsBuiltReport.Core' + $Commands.Count | Should -BeGreaterThan 0 + } + + It 'Should not expose most private functions' { + $Commands = Get-Command -Module 'AsBuiltReport.Core' -CommandType Function + # Note: Get-RequiredModule and Write-ReportModuleInfo are intentionally made global for report modules + $Commands.Name | Should -Not -Contain 'Initialize-LocalizedData' + $Commands.Name | Should -Not -Contain 'Resolve-Culture' + $Commands.Name | Should -Not -Contain 'Draw-AsciiBanner' + } + } + + Context 'Module Dependencies' { + It 'Should have PScribo module as a required module' { + $Module = Get-Module -Name 'AsBuiltReport.Core' + $Module.RequiredModules.Name | Should -Contain 'PScribo' + } + + It 'Should load PScribo module' { + Get-Module -Name 'PScribo' | Should -Not -BeNullOrEmpty + } + } + + Context 'Module Version' { + It 'Should have a valid semantic version' { + $Module = Get-Module -Name 'AsBuiltReport.Core' + $Module.Version | Should -Not -BeNullOrEmpty + $Module.Version.GetType().Name | Should -Be 'Version' + } + + It 'Should have version components' { + $Module = Get-Module -Name 'AsBuiltReport.Core' + $Module.Version.Major | Should -BeGreaterOrEqual 0 + $Module.Version.Minor | Should -BeGreaterOrEqual 0 + } + } + + Context 'Module Metadata' { + BeforeAll { + $Module = Get-Module -Name 'AsBuiltReport.Core' + } + + It 'Should have company or author information' { + $Module.CompanyName -or $Module.Author | Should -Not -BeNullOrEmpty + } + + It 'Should have copyright information' { + $Module.Copyright | Should -Not -BeNullOrEmpty + } + + It 'Should have a description' { + $Module.Description | Should -Not -BeNullOrEmpty + } + + It 'Should have a valid GUID' { + $Module.Guid | Should -Not -BeNullOrEmpty + [Guid]::TryParse($Module.Guid, [ref][Guid]::Empty) | Should -Be $true + } + } + + Context 'Language Support' { + BeforeAll { + $ModuleBase = (Get-Module -Name 'AsBuiltReport.Core').ModuleBase + $LanguagePath = Join-Path -Path $ModuleBase -ChildPath 'Language' + } + + It 'Should have a Language folder' { + Test-Path -Path $LanguagePath | Should -Be $true + } + + It 'Should have en-US language support' { + $EnUSPath = Join-Path -Path $LanguagePath -ChildPath 'en-US' + Test-Path -Path $EnUSPath | Should -Be $true + } + + It 'Should have localization files in en-US' { + $EnUSPath = Join-Path -Path $LanguagePath -ChildPath 'en-US' + $LocalizationFiles = Get-ChildItem -Path $EnUSPath -Filter '*.psd1' -ErrorAction SilentlyContinue + $LocalizationFiles.Count | Should -BeGreaterThan 0 + } + + It 'Should have valid localization data files' { + $EnUSPath = Join-Path -Path $LanguagePath -ChildPath 'en-US' + $LocalizationFiles = Get-ChildItem -Path $EnUSPath -Filter '*.psd1' + foreach ($File in $LocalizationFiles) { + # All .psd1 files in Language folder use ConvertFrom-StringData and should be loaded with Import-LocalizedData + { + $null = Import-LocalizedData -BaseDirectory $File.Directory.FullName -FileName $File.Name -ErrorAction Stop + } | Should -Not -Throw + } + } + + It 'Should support multiple languages' { + $LanguageFolders = Get-ChildItem -Path $LanguagePath -Directory + $LanguageFolders.Count | Should -BeGreaterThan 1 + } + } +} + +AfterAll { + # Clean up + Remove-Module -Name 'AsBuiltReport.Core' -Force -ErrorAction SilentlyContinue +} diff --git a/Tests/Invoke-Tests.ps1 b/Tests/Invoke-Tests.ps1 new file mode 100644 index 0000000..b5cd529 --- /dev/null +++ b/Tests/Invoke-Tests.ps1 @@ -0,0 +1,273 @@ +<# +.SYNOPSIS + Helper script to run AsBuiltReport.Core Pester tests locally. + +.DESCRIPTION + This script provides an easy way to run Pester tests for the AsBuiltReport.Core module. + It handles module installation, test execution, and result reporting. + +.PARAMETER TestType + Specifies which tests to run. Options: All, Unit, Integration, Quality + Default: All + +.PARAMETER CodeCoverage + Enable code coverage analysis. + +.PARAMETER OutputFormat + Specifies the output format for test results. Options: Console, NUnitXml, JUnitXml + Default: Console + +.PARAMETER ShowCodeCoverage + Display code coverage results after test execution. + +.EXAMPLE + .\Invoke-Tests.ps1 + Runs all tests with console output. + +.EXAMPLE + .\Invoke-Tests.ps1 -TestType Unit + Runs only unit tests. + +.EXAMPLE + .\Invoke-Tests.ps1 -CodeCoverage -ShowCodeCoverage + Runs all tests with code coverage analysis and displays coverage report. + +.EXAMPLE + .\Invoke-Tests.ps1 -TestType Quality -OutputFormat NUnitXml + Runs quality tests and exports results to NUnit XML format. +#> + +[CmdletBinding()] +param( + [Parameter()] + [ValidateSet('All', 'Unit', 'Integration', 'Quality')] + [string]$TestType = 'All', + + [Parameter()] + [switch]$CodeCoverage, + + [Parameter()] + [ValidateSet('Console', 'NUnitXml', 'JUnitXml')] + [string]$OutputFormat = 'Console', + + [Parameter()] + [switch]$ShowCodeCoverage +) + +# Set strict mode +Set-StrictMode -Version Latest +$ErrorActionPreference = 'Stop' + +# Script variables +$ScriptRoot = Split-Path -Path $PSScriptRoot -Parent +$TestsPath = $PSScriptRoot +$ModulePath = Join-Path -Path $ScriptRoot -ChildPath 'AsBuiltReport.Core' + +Write-Host "`n========================================" -ForegroundColor Cyan +Write-Host " AsBuiltReport.Core Test Runner" -ForegroundColor Cyan +Write-Host "========================================`n" -ForegroundColor Cyan + +# Check if Tests directory exists +if (-not (Test-Path $TestsPath)) { + Write-Error "Tests directory not found at: $TestsPath" + exit 1 +} + +# Check PowerShell version +Write-Host "PowerShell Version: $($PSVersionTable.PSVersion)" -ForegroundColor Yellow + +# Check if running in PowerShell 7+ +if ($PSVersionTable.PSVersion.Major -lt 7) { + Write-Warning "These tests are designed for PowerShell 7+. You are running PowerShell $($PSVersionTable.PSVersion). Some tests may fail." +} + +# Install required modules +Write-Host "`nChecking required modules..." -ForegroundColor Cyan + +$RequiredModules = @( + @{ Name = 'Pester'; MinimumVersion = '5.0.0' } + @{ Name = 'PSScriptAnalyzer'; MinimumVersion = '1.0.0' } + @{ Name = 'PScribo'; MinimumVersion = '0.11.1' } +) + +foreach ($Module in $RequiredModules) { + $InstalledModule = Get-Module -ListAvailable -Name $Module.Name | + Where-Object { $_.Version -ge [Version]$Module.MinimumVersion } | + Sort-Object Version -Descending | + Select-Object -First 1 + + if ($InstalledModule) { + Write-Host " [OK] $($Module.Name) v$($InstalledModule.Version)" -ForegroundColor Green + } else { + Write-Host " [MISSING] $($Module.Name) (minimum version: $($Module.MinimumVersion))" -ForegroundColor Yellow + Write-Host " Installing $($Module.Name)..." -ForegroundColor Yellow + + try { + Install-Module -Name $Module.Name -MinimumVersion $Module.MinimumVersion -Force -SkipPublisherCheck -Scope CurrentUser + Write-Host " [OK] $($Module.Name) installed" -ForegroundColor Green + } catch { + Write-Error "Failed to install $($Module.Name): $_" + exit 1 + } + } +} + +# Import Pester +Import-Module Pester -MinimumVersion 5.0.0 -Force + +# Determine test path based on TestType +$TestPath = switch ($TestType) { + 'Unit' { Join-Path -Path $TestsPath -ChildPath 'Unit' } + 'Integration' { Join-Path -Path $TestsPath -ChildPath 'Integration' } + 'Quality' { Join-Path -Path $TestsPath -ChildPath 'Quality' } + 'All' { $TestsPath } +} + +if (-not (Test-Path $TestPath)) { + Write-Warning "Test path not found: $TestPath" + Write-Host "Creating directory: $TestPath" + New-Item -Path $TestPath -ItemType Directory -Force | Out-Null +} + +Write-Host "`nTest Configuration:" -ForegroundColor Cyan +Write-Host " Test Type: $TestType" -ForegroundColor White +Write-Host " Test Path: $TestPath" -ForegroundColor White +Write-Host " Code Coverage: $($CodeCoverage.IsPresent)" -ForegroundColor White +Write-Host " Output Format: $OutputFormat" -ForegroundColor White + +# Configure Pester +$PesterConfiguration = New-PesterConfiguration + +# Set test path +$PesterConfiguration.Run.Path = $TestPath +$PesterConfiguration.Run.PassThru = $true +$PesterConfiguration.Output.Verbosity = 'Detailed' + +# Configure code coverage +if ($CodeCoverage) { + $PesterConfiguration.CodeCoverage.Enabled = $true + # Get all .ps1 and .psm1 files in the module (excluding Tests directory) + $CoverageFiles = Get-ChildItem -Path $ModulePath -Include '*.ps1', '*.psm1' -Recurse | Where-Object { $_.FullName -notmatch '\\Tests\\' } + if ($CoverageFiles) { + $PesterConfiguration.CodeCoverage.Path = $CoverageFiles.FullName + $PesterConfiguration.CodeCoverage.OutputFormat = 'JaCoCo' + $PesterConfiguration.CodeCoverage.OutputPath = Join-Path -Path $ScriptRoot -ChildPath 'coverage.xml' + } else { + Write-Warning "No files found for code coverage analysis in: $ModulePath" + $CodeCoverage = $false + $PesterConfiguration.CodeCoverage.Enabled = $false + } +} + +# Configure test results output +if ($OutputFormat -ne 'Console') { + $PesterConfiguration.TestResult.Enabled = $true + $PesterConfiguration.TestResult.OutputFormat = $OutputFormat + $OutputFileName = "testResults.$(if ($OutputFormat -eq 'NUnitXml') { 'xml' } else { 'xml' })" + $PesterConfiguration.TestResult.OutputPath = Join-Path -Path $ScriptRoot -ChildPath $OutputFileName +} + +# Run Pester tests +Write-Host "`n========================================" -ForegroundColor Cyan +Write-Host " Running Tests" -ForegroundColor Cyan +Write-Host "========================================`n" -ForegroundColor Cyan + +try { + $TestResults = Invoke-Pester -Configuration $PesterConfiguration +} catch { + Write-Error "Test execution failed: $_" + exit 1 +} + +# Display results summary +Write-Host "`n========================================" -ForegroundColor Cyan +Write-Host " Test Results Summary" -ForegroundColor Cyan +Write-Host "========================================`n" -ForegroundColor Cyan + +Write-Host "Total Tests: $($TestResults.TotalCount)" -ForegroundColor White +Write-Host "Passed: $($TestResults.PassedCount)" -ForegroundColor Green +Write-Host "Failed: $($TestResults.FailedCount)" -ForegroundColor $(if ($TestResults.FailedCount -gt 0) { 'Red' } else { 'Green' }) +Write-Host "Skipped: $($TestResults.SkippedCount)" -ForegroundColor Yellow +Write-Host "Not Run: $($TestResults.NotRunCount)" -ForegroundColor Gray + +if ($TestResults.Duration) { + Write-Host "Duration: $($TestResults.Duration.ToString('mm\:ss\.fff'))" -ForegroundColor White +} + +# Display failed tests +if ($TestResults.FailedCount -gt 0) { + Write-Host "`n========================================" -ForegroundColor Red + Write-Host " Failed Tests" -ForegroundColor Red + Write-Host "========================================`n" -ForegroundColor Red + + foreach ($FailedTest in $TestResults.Failed) { + Write-Host " $($FailedTest.ExpandedName)" -ForegroundColor Red + if ($FailedTest.ErrorRecord) { + Write-Host " Error: $($FailedTest.ErrorRecord.Exception.Message)" -ForegroundColor Yellow + } + } +} + +# Display code coverage +if ($CodeCoverage -and $ShowCodeCoverage) { + Write-Host "`n========================================" -ForegroundColor Cyan + Write-Host " Code Coverage" -ForegroundColor Cyan + Write-Host "========================================`n" -ForegroundColor Cyan + + $Coverage = $TestResults.CodeCoverage + if ($Coverage) { + # Pester 5 CodeCoverage object structure + # The coverage info is displayed by Pester itself during test run + # We can access: CoveragePercent, AnalyzedFiles, ExecutedCommands, MissedCommands + + try { + if ($Coverage.CoveragePercent) { + $CoveragePercent = [math]::Round($Coverage.CoveragePercent, 2) + $CoverageColor = if ($CoveragePercent -ge 80) { 'Green' } elseif ($CoveragePercent -ge 60) { 'Yellow' } else { 'Red' } + Write-Host "Coverage: $CoveragePercent%" -ForegroundColor $CoverageColor + } + + if ($Coverage.AnalyzedFiles) { + Write-Host "Files Analyzed: $($Coverage.AnalyzedFiles.Count)" -ForegroundColor White + } + + if ($Coverage.MissedCommands) { + $MissedCount = $Coverage.MissedCommands.Count + Write-Host "Missed Commands: $MissedCount" -ForegroundColor $(if ($MissedCount -eq 0) { 'Green' } else { 'Yellow' }) + } + } catch { + Write-Host "Code coverage was enabled. See output above for details." -ForegroundColor Cyan + } + } else { + Write-Host "No code coverage data available" -ForegroundColor Yellow + } +} + +# Display output file locations +if ($OutputFormat -ne 'Console') { + Write-Host "`n========================================" -ForegroundColor Cyan + Write-Host " Output Files" -ForegroundColor Cyan + Write-Host "========================================`n" -ForegroundColor Cyan + + $OutputFile = Join-Path -Path $ScriptRoot -ChildPath $OutputFileName + if (Test-Path $OutputFile) { + Write-Host "Test Results: $OutputFile" -ForegroundColor White + } + + if ($CodeCoverage) { + $CoverageFile = Join-Path -Path $ScriptRoot -ChildPath 'coverage.xml' + if (Test-Path $CoverageFile) { + Write-Host "Code Coverage: $CoverageFile" -ForegroundColor White + } + } +} + +# Exit with appropriate code +Write-Host "" +if ($TestResults.FailedCount -eq 0) { + Write-Host "All tests passed!" -ForegroundColor Green + exit 0 +} else { + Write-Host "Some tests failed!" -ForegroundColor Red + exit 1 +} diff --git a/Tests/Quality/CodeQuality.Tests.ps1 b/Tests/Quality/CodeQuality.Tests.ps1 new file mode 100644 index 0000000..f0dccb9 --- /dev/null +++ b/Tests/Quality/CodeQuality.Tests.ps1 @@ -0,0 +1,219 @@ +BeforeAll { + $ModuleRoot = Join-Path -Path $PSScriptRoot -ChildPath '..\..\AsBuiltReport.Core' +} + +Describe 'Code Quality and Best Practices' { + Context 'File Structure' { + It 'Should have a manifest file' { + $ManifestPath = Join-Path -Path $ModuleRoot -ChildPath 'AsBuiltReport.Core.psd1' + Test-Path -Path $ManifestPath | Should -Be $true + } + + It 'Should have a module file' { + $ModulePath = Join-Path -Path $ModuleRoot -ChildPath 'AsBuiltReport.Core.psm1' + Test-Path -Path $ModulePath | Should -Be $true + } + + It 'Should have a Src folder' { + $SrcPath = Join-Path -Path $ModuleRoot -ChildPath 'Src' + Test-Path -Path $SrcPath | Should -Be $true + } + + It 'Should organize functions into Public and Private folders' { + $PublicPath = Join-Path -Path $ModuleRoot -ChildPath 'Src\Public' + $PrivatePath = Join-Path -Path $ModuleRoot -ChildPath 'Src\Private' + Test-Path -Path $PublicPath | Should -Be $true + Test-Path -Path $PrivatePath | Should -Be $true + } + } + + Context 'PowerShell Best Practices' { + It 'All script files should use UTF8 encoding' { + $ScriptFiles = Get-ChildItem -Path $ModuleRoot -Include '*.ps1', '*.psm1' -Recurse + foreach ($File in $ScriptFiles) { + $Content = [System.IO.File]::ReadAllBytes($File.FullName) + # Check for UTF8 BOM (EF BB BF) or assume UTF8 + if ($Content.Length -ge 3) { + $BOM = $Content[0..2] + # UTF8 BOM or no BOM is acceptable + ($BOM[0] -eq 0xEF -and $BOM[1] -eq 0xBB -and $BOM[2] -eq 0xBF) -or + ($BOM[0] -ne 0xFF -and $BOM[0] -ne 0xFE) | Should -Be $true + } + } + } + + It 'All public functions should have comment-based help' { + $PublicFunctions = Get-ChildItem -Path (Join-Path -Path $ModuleRoot -ChildPath 'Src\Public') -Filter '*.ps1' + foreach ($Function in $PublicFunctions) { + $Content = Get-Content -Path $Function.FullName -Raw + $Content | Should -Match '\.SYNOPSIS' + $Content | Should -Match '\.DESCRIPTION' + $Content | Should -Match '\.EXAMPLE' + } + } + + It 'All public functions should use CmdletBinding' { + $PublicFunctions = Get-ChildItem -Path (Join-Path -Path $ModuleRoot -ChildPath 'Src\Public') -Filter '*.ps1' + foreach ($Function in $PublicFunctions) { + $Content = Get-Content -Path $Function.FullName -Raw + $Content | Should -Match '\[CmdletBinding\(' + } + } + + It 'All functions should use approved verbs' { + $PublicFunctions = Get-ChildItem -Path (Join-Path -Path $ModuleRoot -ChildPath 'Src\Public') -Filter '*.ps1' + $ApprovedVerbs = Get-Verb | Select-Object -ExpandProperty Verb + + foreach ($Function in $PublicFunctions) { + $FunctionName = $Function.BaseName + $Verb = ($FunctionName -split '-')[0] + $ApprovedVerbs | Should -Contain $Verb + } + } + } + + Context 'Code Syntax' { + It 'Should have no syntax errors in PowerShell script files' { + $ScriptFiles = Get-ChildItem -Path $ModuleRoot -Include '*.ps1', '*.psm1' -Recurse + foreach ($File in $ScriptFiles) { + $Errors = $null + $null = [System.Management.Automation.PSParser]::Tokenize( + (Get-Content -Path $File.FullName -Raw), + [ref]$Errors + ) + $Errors.Count | Should -Be 0 -Because "File $($File.Name) should have no syntax errors" + } + } + + It 'Should parse successfully with AST' { + $ScriptFiles = Get-ChildItem -Path $ModuleRoot -Include '*.ps1', '*.psm1' -Recurse + foreach ($File in $ScriptFiles) { + $Errors = $null + $null = [System.Management.Automation.Language.Parser]::ParseFile( + $File.FullName, + [ref]$null, + [ref]$Errors + ) + $Errors.Count | Should -Be 0 -Because "File $($File.Name) should parse without errors" + } + } + } + + Context 'Manifest Validation' { + BeforeAll { + $ManifestPath = Join-Path -Path $ModuleRoot -ChildPath 'AsBuiltReport.Core.psd1' + } + + It 'Should have a valid module manifest' { + { Test-ModuleManifest -Path $ManifestPath -ErrorAction Stop } | Should -Not -Throw + } + + It 'Should specify a RootModule' { + $Manifest = Import-PowerShellDataFile -Path $ManifestPath + $Manifest.RootModule | Should -Not -BeNullOrEmpty + } + + It 'Should specify a ModuleVersion' { + $Manifest = Import-PowerShellDataFile -Path $ManifestPath + $Manifest.ModuleVersion | Should -Not -BeNullOrEmpty + [Version]$Manifest.ModuleVersion | Should -Not -BeNullOrEmpty + } + + It 'Should specify a GUID' { + $Manifest = Import-PowerShellDataFile -Path $ManifestPath + $Manifest.GUID | Should -Not -BeNullOrEmpty + [Guid]::TryParse($Manifest.GUID, [ref][Guid]::Empty) | Should -Be $true + } + + It 'Should specify an Author' { + $Manifest = Import-PowerShellDataFile -Path $ManifestPath + $Manifest.Author | Should -Not -BeNullOrEmpty + } + + It 'Should specify a Description' { + $Manifest = Import-PowerShellDataFile -Path $ManifestPath + $Manifest.Description | Should -Not -BeNullOrEmpty + } + + It 'Should have FunctionsToExport defined' { + $Manifest = Import-PowerShellDataFile -Path $ManifestPath + $Manifest.FunctionsToExport | Should -Not -BeNullOrEmpty + } + + It 'Should not use wildcards for FunctionsToExport' { + $Manifest = Import-PowerShellDataFile -Path $ManifestPath + $Manifest.FunctionsToExport | Should -Not -Contain '*' + } + } + + Context 'Documentation' { + It 'Should have a README file in the repository root' { + $ReadmePath = Join-Path -Path $ModuleRoot -ChildPath '..\README.md' + Test-Path -Path $ReadmePath | Should -Be $true + } + + It 'Should have a CHANGELOG file in the repository root' { + $ChangelogPath = Join-Path -Path $ModuleRoot -ChildPath '..\CHANGELOG.md' + Test-Path -Path $ChangelogPath | Should -Be $true + } + + It 'Should have a LICENSE file in the repository root' { + $LicensePath = Join-Path -Path $ModuleRoot -ChildPath '..\LICENSE' + Test-Path -Path $LicensePath | Should -Be $true + } + } + + Context 'Language Files Quality' { + BeforeAll { + $LanguagePath = Join-Path -Path $ModuleRoot -ChildPath 'Language' + $LanguageFiles = Get-ChildItem -Path $LanguagePath -Filter '*.psd1' -Recurse + } + + It 'All language files should be valid and parseable' { + foreach ($File in $LanguageFiles) { + # All .psd1 files in Language folder use ConvertFrom-StringData and should be loaded with Import-LocalizedData + { + $null = Import-LocalizedData -BaseDirectory $File.Directory.FullName -FileName $File.Name -ErrorAction Stop + } | Should -Not -Throw + } + } + + It 'All language files should contain hashtable data' { + foreach ($File in $LanguageFiles) { + # All language files should be loaded with Import-LocalizedData + $Data = Import-LocalizedData -BaseDirectory $File.Directory.FullName -FileName $File.Name + $Data.GetType().Name | Should -Be 'Hashtable' + } + } + + It 'Language files should have consistent keys across cultures' { + # Get all language folders + $LanguageFolders = Get-ChildItem -Path $LanguagePath -Directory + + # Get all unique language file names + $FileNames = $LanguageFiles | Select-Object -ExpandProperty Name -Unique + + foreach ($FileName in $FileNames) { + $Keys = @{} + + # Collect keys from each culture's version of this file + foreach ($Folder in $LanguageFolders) { + $FilePath = Join-Path -Path $Folder.FullName -ChildPath $FileName + if (Test-Path $FilePath) { + # All language files should be loaded with Import-LocalizedData + $Data = Import-LocalizedData -BaseDirectory $Folder.FullName -FileName $FileName + $Keys[$Folder.Name] = $Data.Keys | Sort-Object + } + } + + # All cultures with this file should have the same keys + if ($Keys.Count -gt 1) { + $ReferenceKeys = $Keys.Values | Select-Object -First 1 + foreach ($CultureKeys in $Keys.Values) { + Compare-Object -ReferenceObject $ReferenceKeys -DifferenceObject $CultureKeys | Should -BeNullOrEmpty + } + } + } + } + } +} diff --git a/Tests/README.md b/Tests/README.md new file mode 100644 index 0000000..5bc0430 --- /dev/null +++ b/Tests/README.md @@ -0,0 +1,213 @@ +# AsBuiltReport.Core Tests + +This directory contains comprehensive Pester tests for the AsBuiltReport.Core PowerShell module. + +## Test Structure + +The tests are organized into the following categories: + +### Root Level Tests +- **AsBuiltReport.Core.Tests.ps1**: Main module-level tests including manifest validation, module structure, and exported functions + +### Unit Tests (`Unit/`) +Unit tests focus on individual functions in isolation: +- **New-AsBuiltReport.Tests.ps1**: Tests for the main report generation function +- **New-AsBuiltReportConfig.Tests.ps1**: Tests for report configuration creation +- **New-AsBuiltConfig.Tests.ps1**: Tests for As Built configuration creation + +### Integration Tests (`Integration/`) +Integration tests verify that components work together correctly: +- **ModuleImport.Tests.ps1**: Tests module loading, dependencies, and initialization + +### Quality Tests (`Quality/`) +Quality tests ensure code meets standards and best practices: +- **CodeQuality.Tests.ps1**: Tests for code structure, syntax, documentation, and PowerShell best practices + +## Running Tests + +### Prerequisites +Ensure you have the following modules installed: +```powershell +Install-Module -Name Pester -MinimumVersion 5.0.0 -Force +Install-Module -Name PSScriptAnalyzer -Force +Install-Module -Name PScribo -MinimumVersion 0.11.1 -Force +``` + +### Using the Invoke-Tests Helper Script (Recommended) +The easiest way to run tests is using the included helper script: +```powershell +# Run all tests +.\Tests\Invoke-Tests.ps1 + +# Run specific test category +.\Tests\Invoke-Tests.ps1 -TestType Unit +.\Tests\Invoke-Tests.ps1 -TestType Integration +.\Tests\Invoke-Tests.ps1 -TestType Quality + +# Run with code coverage +.\Tests\Invoke-Tests.ps1 -CodeCoverage -ShowCodeCoverage + +# Export results to XML +.\Tests\Invoke-Tests.ps1 -OutputFormat NUnitXml +``` + +### Run Tests Manually with Invoke-Pester +```powershell +# Run all tests with default configuration +Invoke-Pester -Path ./Tests + +# Run all tests with detailed output +Invoke-Pester -Path ./Tests -Output Detailed + +# Run specific test categories +Invoke-Pester -Path ./Tests/Unit +Invoke-Pester -Path ./Tests/Integration +Invoke-Pester -Path ./Tests/Quality +``` + +### Run with Code Coverage +```powershell +$PesterConfiguration = New-PesterConfiguration +$PesterConfiguration.Run.Path = './Tests' +$PesterConfiguration.CodeCoverage.Enabled = $true +$PesterConfiguration.CodeCoverage.Path = './AsBuiltReport.Core/**/*.ps1' +$PesterConfiguration.CodeCoverage.OutputFormat = 'JaCoCo' +$PesterConfiguration.CodeCoverage.OutputPath = './coverage.xml' +$PesterConfiguration.Output.Verbosity = 'Detailed' + +Invoke-Pester -Configuration $PesterConfiguration +``` + +### Run with Test Results Export +```powershell +$PesterConfiguration = New-PesterConfiguration +$PesterConfiguration.Run.Path = './Tests' +$PesterConfiguration.TestResult.Enabled = $true +$PesterConfiguration.TestResult.OutputFormat = 'NUnitXml' +$PesterConfiguration.TestResult.OutputPath = './testResults.xml' +$PesterConfiguration.Output.Verbosity = 'Detailed' + +Invoke-Pester -Configuration $PesterConfiguration +``` + +## Continuous Integration + +The tests are automatically run on every push and pull request via GitHub Actions. See `.github/workflows/Pester.yml` for the CI/CD pipeline configuration. + +### CI/CD Pipeline Features +- **Windows Testing**: Tests run on Windows Server (latest) +- **Uses Invoke-Tests.ps1**: Same script developers use locally +- **Code Coverage**: Automatic code coverage analysis and reporting +- **PSScriptAnalyzer**: Static code analysis for PowerShell best practices +- **Test Result Artifacts**: Test results and coverage uploaded as artifacts + +## Test Coverage + +The test suite covers: + +### Module Structure +- Module manifest validation +- File structure and organization +- Required dependencies +- Version information +- Module metadata + +### Public Functions +- Parameter validation +- Parameter aliases +- Help documentation +- Argument completers +- Function behavior +- Error handling + +### Code Quality +- PowerShell syntax validation +- Best practices compliance +- Comment-based help +- Approved verb usage +- Language file consistency +- Documentation completeness + +### Integration +- Module import/export +- Dependency loading +- Language support +- Function availability + +## Writing New Tests + +When adding new tests, follow these guidelines: + +1. **Use Pester 5 syntax**: Use `BeforeAll`, `It`, `Should` syntax +2. **Organize by category**: Place tests in appropriate folders (Unit, Integration, Quality) +3. **Use descriptive names**: Test names should clearly describe what is being tested +4. **Include cleanup**: Use `AfterAll` to clean up resources +5. **Mock external dependencies**: Use `Mock` for external calls +6. **Test both success and failure paths**: Include positive and negative test cases + +### Example Test Template +```powershell +BeforeAll { + $ModulePath = Join-Path -Path $PSScriptRoot -ChildPath '..\..\AsBuiltReport.Core\AsBuiltReport.Core.psd1' + Import-Module $ModulePath -Force +} + +Describe 'YourFunction Tests' { + Context 'Parameter Validation' { + It 'Should have expected parameter' { + $Command = Get-Command -Name 'YourFunction' + $Command.Parameters.Keys | Should -Contain 'ParameterName' + } + } + + Context 'Function Behavior' { + It 'Should return expected output' { + # Your test here + } + } +} + +AfterAll { + Remove-Module -Name 'AsBuiltReport.Core' -Force -ErrorAction SilentlyContinue +} +``` + +## Test Results + +Test results are available in multiple formats: +- **Console Output**: Real-time test execution feedback +- **NUnit XML**: Compatible with most CI/CD systems +- **JaCoCo XML**: Code coverage reporting format +- **GitHub Actions Summary**: Visual test results in GitHub UI + +## Troubleshooting + +### Tests Fail Locally But Pass in CI +- Ensure you have the same PowerShell version (7.4) +- Check module dependencies are installed +- Clear PowerShell module cache: `Remove-Module -Name AsBuiltReport.Core -Force` + +### Code Coverage Not Generated +- Verify Pester 5.0+ is installed: `Get-Module -ListAvailable Pester` +- Check file paths in coverage configuration +- Ensure tests are actually executing functions in the module + +### PSScriptAnalyzer Errors +- Review PSScriptAnalyzer settings in `.github/workflows/PSScriptAnalyzerSettings.psd1` +- Run locally: `Invoke-ScriptAnalyzer -Path ./AsBuiltReport.Core -Recurse` +- Fix issues identified or update suppression rules if needed + +## Contributing + +When contributing to AsBuiltReport.Core: +1. Add tests for new functionality +2. Ensure all tests pass before submitting PR +3. Maintain or improve code coverage +4. Follow PowerShell best practices +5. Update this README if adding new test categories + +## Resources + +- [Pester Documentation](https://pester.dev/) +- [PSScriptAnalyzer Rules](https://github.com/PowerShell/PSScriptAnalyzer) +- [PowerShell Best Practices](https://learn.microsoft.com/en-us/powershell/scripting/developer/cmdlet/strongly-encouraged-development-guidelines) diff --git a/Tests/Unit/Draw-AsciiBanner.Tests.ps1 b/Tests/Unit/Draw-AsciiBanner.Tests.ps1 new file mode 100644 index 0000000..407677c --- /dev/null +++ b/Tests/Unit/Draw-AsciiBanner.Tests.ps1 @@ -0,0 +1,177 @@ +BeforeAll { + # Import the module + $ModulePath = Join-Path -Path $PSScriptRoot -ChildPath '..\..\AsBuiltReport.Core\AsBuiltReport.Core.psd1' + Import-Module $ModulePath -Force +} + +Describe 'Draw-AsciiBanner Unit Tests' { + Context 'Function Exists' { + It 'Should have Draw-AsciiBanner function available' { + InModuleScope 'AsBuiltReport.Core' { + $Function = Get-Command -Name 'Draw-AsciiBanner' -ErrorAction SilentlyContinue + $Function | Should -Not -BeNullOrEmpty + } + } + } + + Context 'Basic Functionality' { + It 'Should call Write-Host when drawing banner' { + InModuleScope 'AsBuiltReport.Core' { + Mock Write-Host { } + Draw-AsciiBanner -Lines @('Test') -TextColor 'Cyan' -SeparatorColor 'Cyan' + Should -Invoke Write-Host -Times 3 + } + } + + It 'Should draw separators and text with single line' { + InModuleScope 'AsBuiltReport.Core' { + Mock Write-Host { } + Draw-AsciiBanner -Lines @('Test Line') -TextColor 'Green' -SeparatorColor 'Yellow' + Should -Invoke Write-Host -Times 3 + } + } + + It 'Should draw separators and text with multiple lines' { + InModuleScope 'AsBuiltReport.Core' { + Mock Write-Host { } + Draw-AsciiBanner -Lines @('Line 1', 'Line 2', 'Line 3') -TextColor 'White' -SeparatorColor 'Cyan' + Should -Invoke Write-Host -Times 5 + } + } + + It 'Should use specified text color' { + InModuleScope 'AsBuiltReport.Core' { + Mock Write-Host { } + Draw-AsciiBanner -Lines @('Test') -TextColor 'Red' -SeparatorColor 'Blue' + Should -Invoke Write-Host -ParameterFilter { $ForegroundColor -eq 'Red' } -Times 1 + } + } + + It 'Should use specified separator color' { + InModuleScope 'AsBuiltReport.Core' { + Mock Write-Host { } + Draw-AsciiBanner -Lines @('Test') -TextColor 'Red' -SeparatorColor 'Blue' + Should -Invoke Write-Host -ParameterFilter { $ForegroundColor -eq 'Blue' } -Times 2 + } + } + + It 'Should handle empty lines array' { + InModuleScope 'AsBuiltReport.Core' { + Mock Write-Host { } + Draw-AsciiBanner -Lines @() -TextColor 'Cyan' -SeparatorColor 'Cyan' + Should -Invoke Write-Host -Times 2 + } + } + + It 'Should accept custom separator length' { + InModuleScope 'AsBuiltReport.Core' { + Mock Write-Host { } + Draw-AsciiBanner -Lines @('Test') -TextColor 'Cyan' -SeparatorColor 'Cyan' -SeparatorLength 80 + Should -Invoke Write-Host -Times 3 + } + } + } + + Context 'Parameter Validation' { + It 'Should accept Lines parameter as string array' { + InModuleScope 'AsBuiltReport.Core' { + Mock Write-Host { } + { Draw-AsciiBanner -Lines @('Test1', 'Test2') -TextColor 'Cyan' -SeparatorColor 'Cyan' } | Should -Not -Throw + } + } + + It 'Should accept TextColor parameter' { + InModuleScope 'AsBuiltReport.Core' { + Mock Write-Host { } + { Draw-AsciiBanner -Lines @('Test') -TextColor 'Green' -SeparatorColor 'Cyan' } | Should -Not -Throw + } + } + + It 'Should accept SeparatorColor parameter' { + InModuleScope 'AsBuiltReport.Core' { + Mock Write-Host { } + { Draw-AsciiBanner -Lines @('Test') -TextColor 'Cyan' -SeparatorColor 'Yellow' } | Should -Not -Throw + } + } + + It 'Should accept SeparatorLength parameter' { + InModuleScope 'AsBuiltReport.Core' { + Mock Write-Host { } + { Draw-AsciiBanner -Lines @('Test') -TextColor 'Cyan' -SeparatorColor 'Cyan' -SeparatorLength 100 } | Should -Not -Throw + } + } + + It 'Should use default SeparatorLength of 60 when not specified' { + InModuleScope 'AsBuiltReport.Core' { + Mock Write-Host { param($Object) $script:LastSeparator = $Object } + Draw-AsciiBanner -Lines @() -TextColor 'Cyan' -SeparatorColor 'Cyan' + $script:LastSeparator.Length | Should -Be 60 + } + } + } + + Context 'Content Formatting' { + It 'Should add padding to text lines' { + InModuleScope 'AsBuiltReport.Core' { + Mock Write-Host { param($Object) $script:Output += @($Object) } + $script:Output = @() + Draw-AsciiBanner -Lines @('Test') -TextColor 'Cyan' -SeparatorColor 'Cyan' + $TextLine = $script:Output | Where-Object { $_ -match 'Test' } + $TextLine | Should -BeLike ' Test' + } + } + + It 'Should format multiple lines correctly' { + InModuleScope 'AsBuiltReport.Core' { + Mock Write-Host { param($Object) $script:Output += @($Object) } + $script:Output = @() + Draw-AsciiBanner -Lines @('Line1', 'Line2') -TextColor 'Cyan' -SeparatorColor 'Cyan' + $script:Output[1] | Should -BeLike ' Line1' + $script:Output[2] | Should -BeLike ' Line2' + } + } + + It 'Should use horizontal line character for separator' { + InModuleScope 'AsBuiltReport.Core' { + Mock Write-Host { param($Object) $script:Output += @($Object) } + $script:Output = @() + Draw-AsciiBanner -Lines @() -TextColor 'Cyan' -SeparatorColor 'Cyan' + # Check separator line properties instead of exact character match + # This handles encoding differences between PS 5.1 and PS 7.x + $separator = $script:Output[0] + $separator.Length | Should -Be 60 + # Verify all characters in the separator are the same + $uniqueChars = $separator.ToCharArray() | Select-Object -Unique + $uniqueChars.Count | Should -Be 1 + # Verify it's the expected Unicode character (0x2500) + [int][char]$uniqueChars[0] | Should -Be 0x2500 + } + } + } + + Context 'Integration with Console Colors' { + It 'Should accept standard console color for text' { + InModuleScope 'AsBuiltReport.Core' { + $Colors = @('Cyan', 'Yellow', 'Green', 'Red', 'Blue') + Mock Write-Host { } + foreach ($Color in $Colors) { + { Draw-AsciiBanner -Lines @('Test') -TextColor $Color -SeparatorColor 'Cyan' } | Should -Not -Throw + } + } + } + + It 'Should accept standard console color for separator' { + InModuleScope 'AsBuiltReport.Core' { + $Colors = @('Cyan', 'Yellow', 'Green', 'Red', 'Blue') + Mock Write-Host { } + foreach ($Color in $Colors) { + { Draw-AsciiBanner -Lines @('Test') -TextColor 'White' -SeparatorColor $Color } | Should -Not -Throw + } + } + } + } +} + +AfterAll { + Remove-Module -Name 'AsBuiltReport.Core' -Force -ErrorAction SilentlyContinue +} diff --git a/Tests/Unit/Get-RequiredModule.Tests.ps1 b/Tests/Unit/Get-RequiredModule.Tests.ps1 new file mode 100644 index 0000000..f3736d9 --- /dev/null +++ b/Tests/Unit/Get-RequiredModule.Tests.ps1 @@ -0,0 +1,140 @@ +BeforeAll { + # Import the module + $ModulePath = Join-Path -Path $PSScriptRoot -ChildPath '..\..\AsBuiltReport.Core\AsBuiltReport.Core.psd1' + Import-Module $ModulePath -Force +} + +Describe 'Get-RequiredModule Unit Tests' { + Context 'Function Exists' { + It 'Should have Get-RequiredModule function available' { + InModuleScope 'AsBuiltReport.Core' { + $Function = Get-Command -Name 'Get-RequiredModule' -ErrorAction SilentlyContinue + $Function | Should -Not -BeNullOrEmpty + } + } + + It 'Should be a CmdletBinding function' { + InModuleScope 'AsBuiltReport.Core' { + $Function = Get-Command -Name 'Get-RequiredModule' + $Function.CmdletBinding | Should -Be $true + } + } + } + + Context 'Parameter Validation' { + It 'Should have Name parameter' { + InModuleScope 'AsBuiltReport.Core' { + $Command = Get-Command -Name 'Get-RequiredModule' + $Command.Parameters.Keys | Should -Contain 'Name' + } + } + + It 'Should have Version parameter' { + InModuleScope 'AsBuiltReport.Core' { + $Command = Get-Command -Name 'Get-RequiredModule' + $Command.Parameters.Keys | Should -Contain 'Version' + } + } + + It 'Should have Name as mandatory parameter' { + InModuleScope 'AsBuiltReport.Core' { + $Command = Get-Command -Name 'Get-RequiredModule' + $Parameter = $Command.Parameters['Name'] + $Parameter.Attributes.Mandatory | Should -Contain $true + } + } + + It 'Should have Version as mandatory parameter' { + InModuleScope 'AsBuiltReport.Core' { + $Command = Get-Command -Name 'Get-RequiredModule' + $Parameter = $Command.Parameters['Version'] + $Parameter.Attributes.Mandatory | Should -Contain $true + } + } + } + + Context 'Module Version Checking' { + It 'Should pass when module version meets requirement' { + InModuleScope 'AsBuiltReport.Core' { + Mock Get-Module { + [PSCustomObject]@{ + Name = 'TestModule' + Version = [Version]'2.0.0' + } + } + $global:translate = @{ + RequiredModuleNotInstalled = 'Module {0} version {1} or higher is required' + RequiredModuleTooOld = 'Module {0} version {1} is installed, but version {2} or higher is required' + } + { Get-RequiredModule -Name 'TestModule' -Version '1.0.0' } | Should -Not -Throw + } + } + + It 'Should pass when module version exactly matches requirement' { + InModuleScope 'AsBuiltReport.Core' { + Mock Get-Module { + [PSCustomObject]@{ + Name = 'TestModule' + Version = [Version]'2.0.0' + } + } + $global:translate = @{ + RequiredModuleNotInstalled = 'Module {0} version {1} or higher is required' + RequiredModuleTooOld = 'Module {0} version {1} is installed, but version {2} or higher is required' + } + { Get-RequiredModule -Name 'TestModule' -Version '2.0.0' } | Should -Not -Throw + } + } + + It 'Should throw when module is not installed' { + InModuleScope 'AsBuiltReport.Core' { + Mock Get-Module { $null } + $global:translate = @{ + RequiredModuleNotInstalled = 'Module {0} version {1} or higher is required' + RequiredModuleTooOld = 'Module {0} version {1} is installed, but version {2} or higher is required' + } + { Get-RequiredModule -Name 'NonExistentModule' -Version '1.0.0' } | Should -Throw + } + } + + It 'Should throw when module version is too old' { + InModuleScope 'AsBuiltReport.Core' { + Mock Get-Module { + [PSCustomObject]@{ + Name = 'TestModule' + Version = [Version]'1.0.0' + } + } + $global:translate = @{ + RequiredModuleNotInstalled = 'Module {0} version {1} or higher is required' + RequiredModuleTooOld = 'Module {0} version {1} is installed, but version {2} or higher is required' + } + { Get-RequiredModule -Name 'TestModule' -Version '2.0.0' } | Should -Throw + } + } + + It 'Should call Get-Module with correct parameters' { + InModuleScope 'AsBuiltReport.Core' { + Mock Get-Module { + [PSCustomObject]@{ + Name = 'TestModule' + Version = [Version]'2.0.0' + } + } + $global:translate = @{ + RequiredModuleNotInstalled = 'Module {0} version {1} or higher is required' + RequiredModuleTooOld = 'Module {0} version {1} is installed, but version {2} or higher is required' + } + Get-RequiredModule -Name 'TestModule' -Version '1.0.0' + Should -Invoke Get-Module -ParameterFilter { + $ListAvailable -eq $true -and $Name -eq 'TestModule' + } + } + } + } +} + +AfterAll { + Remove-Module -Name 'AsBuiltReport.Core' -Force -ErrorAction SilentlyContinue + Remove-Variable -Name 'translate' -Scope Global -ErrorAction SilentlyContinue +} diff --git a/Tests/Unit/Initialize-LocalizedData.Tests.ps1 b/Tests/Unit/Initialize-LocalizedData.Tests.ps1 new file mode 100644 index 0000000..977405d --- /dev/null +++ b/Tests/Unit/Initialize-LocalizedData.Tests.ps1 @@ -0,0 +1,126 @@ +BeforeAll { + # Import the module + $ModulePath = Join-Path -Path $PSScriptRoot -ChildPath '..\..\AsBuiltReport.Core\AsBuiltReport.Core.psd1' + Import-Module $ModulePath -Force +} + +Describe 'Initialize-LocalizedData Unit Tests' { + Context 'Function Exists' { + It 'Should have Initialize-LocalizedData function available' { + InModuleScope 'AsBuiltReport.Core' { + $Function = Get-Command -Name 'Initialize-LocalizedData' -ErrorAction SilentlyContinue + $Function | Should -Not -BeNullOrEmpty + } + } + + It 'Should be a CmdletBinding function' { + InModuleScope 'AsBuiltReport.Core' { + $Function = Get-Command -Name 'Initialize-LocalizedData' + $Function.CmdletBinding | Should -Be $true + } + } + } + + Context 'Parameter Validation' { + It 'Should have ModuleBasePath parameter' { + InModuleScope 'AsBuiltReport.Core' { + $Command = Get-Command -Name 'Initialize-LocalizedData' + $Command.Parameters.Keys | Should -Contain 'ModuleBasePath' + } + } + + It 'Should have LanguageFile parameter' { + InModuleScope 'AsBuiltReport.Core' { + $Command = Get-Command -Name 'Initialize-LocalizedData' + $Command.Parameters.Keys | Should -Contain 'LanguageFile' + } + } + + It 'Should have ModuleType parameter' { + InModuleScope 'AsBuiltReport.Core' { + $Command = Get-Command -Name 'Initialize-LocalizedData' + $Command.Parameters.Keys | Should -Contain 'ModuleType' + } + } + + It 'Should have Language parameter' { + InModuleScope 'AsBuiltReport.Core' { + $Command = Get-Command -Name 'Initialize-LocalizedData' + $Command.Parameters.Keys | Should -Contain 'Language' + } + } + + It 'Should have ModuleName parameter' { + InModuleScope 'AsBuiltReport.Core' { + $Command = Get-Command -Name 'Initialize-LocalizedData' + $Command.Parameters.Keys | Should -Contain 'ModuleName' + } + } + + It 'Should have ModuleBasePath as mandatory' { + InModuleScope 'AsBuiltReport.Core' { + $Command = Get-Command -Name 'Initialize-LocalizedData' + $Parameter = $Command.Parameters['ModuleBasePath'] + $Parameter.Attributes.Mandatory | Should -Contain $true + } + } + + It 'Should have LanguageFile as mandatory' { + InModuleScope 'AsBuiltReport.Core' { + $Command = Get-Command -Name 'Initialize-LocalizedData' + $Parameter = $Command.Parameters['LanguageFile'] + $Parameter.Attributes.Mandatory | Should -Contain $true + } + } + + It 'Should validate ModuleType values' { + InModuleScope 'AsBuiltReport.Core' { + $Command = Get-Command -Name 'Initialize-LocalizedData' + $Parameter = $Command.Parameters['ModuleType'] + $ValidateSet = $Parameter.Attributes.Where({$_ -is [System.Management.Automation.ValidateSetAttribute]}) + $ValidateSet.ValidValues | Should -Contain 'Core' + $ValidateSet.ValidValues | Should -Contain 'Report' + } + } + } + + Context 'Culture Detection' { + It 'Should use Get-Culture for Core modules without explicit language' { + InModuleScope 'AsBuiltReport.Core' { + Mock Write-Host { } + Mock Test-Path { $false } + Mock Import-LocalizedData { @{ TestKey = 'TestValue' } } + Mock Get-Culture { [System.Globalization.CultureInfo]::GetCultureInfo('en-US') } + Mock Resolve-Culture { @('en-US') } + + try { + Initialize-LocalizedData -ModuleBasePath $PSScriptRoot -LanguageFile 'TestFile' -ModuleType 'Core' -ErrorAction SilentlyContinue 2>$null + } catch {} + + Should -Invoke Get-Culture + } + } + + It 'Should use specified language when provided' { + InModuleScope 'AsBuiltReport.Core' { + Mock Write-Host { } + Mock Test-Path { $false } + Mock Import-LocalizedData { @{ TestKey = 'TestValue' } } + Mock Get-Culture { [System.Globalization.CultureInfo]::GetCultureInfo('en-US') } + Mock Resolve-Culture { @('fr-FR') } + + try { + Initialize-LocalizedData -ModuleBasePath $PSScriptRoot -LanguageFile 'TestFile' -Language 'fr-FR' -ErrorAction SilentlyContinue 2>$null + } catch {} + + Should -Invoke Resolve-Culture -ParameterFilter { $CultureName -eq 'fr-FR' } + } + } + } +} + +AfterAll { + Remove-Module -Name 'AsBuiltReport.Core' -Force -ErrorAction SilentlyContinue + Remove-Variable -Name 'translate' -Scope Global -ErrorAction SilentlyContinue + Remove-Variable -Name 'AsBuiltReportLocalizedWarnings' -Scope Global -ErrorAction SilentlyContinue +} diff --git a/Tests/Unit/New-AsBuiltConfig.Tests.ps1 b/Tests/Unit/New-AsBuiltConfig.Tests.ps1 new file mode 100644 index 0000000..bc20aae --- /dev/null +++ b/Tests/Unit/New-AsBuiltConfig.Tests.ps1 @@ -0,0 +1,73 @@ +BeforeAll { + # Import the module + $ModulePath = Join-Path -Path $PSScriptRoot -ChildPath '..\..\AsBuiltReport.Core\AsBuiltReport.Core.psd1' + Import-Module $ModulePath -Force +} + +Describe 'New-AsBuiltConfig Unit Tests' { + Context 'Function Exists' { + It 'Should have New-AsBuiltConfig function available' { + Get-Command -Name 'New-AsBuiltConfig' -ErrorAction SilentlyContinue | Should -Not -BeNullOrEmpty + } + } + + Context 'Parameter Validation' { + BeforeAll { + $Command = Get-Command -Name 'New-AsBuiltConfig' + } + + It 'Should not have any mandatory parameters' { + $MandatoryParams = $Command.Parameters.Values | Where-Object { + ($_.Attributes | Where-Object { $_ -is [System.Management.Automation.ParameterAttribute] }).Mandatory -contains $true + } + $MandatoryParams | Should -BeNullOrEmpty + } + + It 'Should be a CmdletBinding function' { + $Command.CmdletBinding | Should -Be $true + } + } + + Context 'Help Documentation' { + BeforeAll { + $Help = Get-Help -Name 'New-AsBuiltConfig' -Full + } + + It 'Should have a synopsis' { + $Help.Synopsis | Should -Not -BeNullOrEmpty + } + + It 'Should have a description' { + $Help.Description | Should -Not -BeNullOrEmpty + } + + It 'Should have examples' { + $Help.Examples | Should -Not -BeNullOrEmpty + $Help.Examples.Example.Count | Should -BeGreaterThan 0 + } + + It 'Should have at least 2 examples' { + $Help.Examples.Example.Count | Should -BeGreaterOrEqual 2 + } + + It 'Should have links' { + $Help.relatedLinks | Should -Not -BeNullOrEmpty + } + + It 'Should reference the user guide' { + $Help.relatedLinks.navigationLink.uri | Should -Match 'asbuiltreport.com|github.com' + } + } + + Context 'Function Output' { + It 'Should return a hashtable when executed non-interactively' { + # Note: This test cannot run in CI/CD as it requires interactive input + # This is a placeholder for manual testing + $true | Should -Be $true + } + } +} + +AfterAll { + Remove-Module -Name 'AsBuiltReport.Core' -Force -ErrorAction SilentlyContinue +} diff --git a/Tests/Unit/New-AsBuiltReport.Tests.ps1 b/Tests/Unit/New-AsBuiltReport.Tests.ps1 new file mode 100644 index 0000000..7e8ad81 --- /dev/null +++ b/Tests/Unit/New-AsBuiltReport.Tests.ps1 @@ -0,0 +1,232 @@ +BeforeAll { + # Import the module + $ModulePath = Join-Path -Path $PSScriptRoot -ChildPath '..\..\AsBuiltReport.Core\AsBuiltReport.Core.psd1' + Import-Module $ModulePath -Force +} + +Describe 'New-AsBuiltReport Unit Tests' { + Context 'Parameter Validation' { + BeforeAll { + $Command = Get-Command -Name 'New-AsBuiltReport' + } + + It 'Should have Report parameter as mandatory' { + $ReportParam = $Command.Parameters['Report'] + ($ReportParam.Attributes | Where-Object { $_ -is [System.Management.Automation.ParameterAttribute] }).Mandatory | Should -Contain $true + } + + It 'Should have Target parameter as mandatory' { + $TargetParam = $Command.Parameters['Target'] + ($TargetParam.Attributes | Where-Object { $_ -is [System.Management.Automation.ParameterAttribute] }).Mandatory | Should -Contain $true + } + + It 'Should have OutputFolderPath parameter as mandatory' { + $OutputParam = $Command.Parameters['OutputFolderPath'] + ($OutputParam.Attributes | Where-Object { $_ -is [System.Management.Automation.ParameterAttribute] }).Mandatory | Should -Contain $true + } + + It 'Should have Credential parameter in Credential parameter set' { + $CredentialParam = $Command.Parameters['Credential'] + $CredentialParam | Should -Not -BeNullOrEmpty + } + + It 'Should have Username and Password parameters in UsernameAndPassword parameter set' { + $Command.Parameters.Keys | Should -Contain 'Username' + $Command.Parameters.Keys | Should -Contain 'Password' + } + + It 'Should have Token parameter in APIToken parameter set' { + $TokenParam = $Command.Parameters['Token'] + $TokenParam | Should -Not -BeNullOrEmpty + } + + It 'Should have UseInteractiveAuth parameter in InteractiveAuth parameter set' { + $Command.Parameters.Keys | Should -Contain 'UseInteractiveAuth' + } + + It 'Format parameter should have default value of Word' { + # Default values are set in the param block, not as attributes + # We can verify this by checking the AST or by testing the actual behavior + # For now, we'll check that the parameter exists and has the correct ValidateSet + $FormatParam = $Command.Parameters['Format'] + $FormatParam | Should -Not -BeNullOrEmpty + } + + It 'Format parameter should accept Word, HTML, and Text' { + $FormatParam = $Command.Parameters['Format'] + $ValidateSetAttribute = $FormatParam.Attributes | Where-Object { $_ -is [System.Management.Automation.ValidateSetAttribute] } + $ValidateSetAttribute.ValidValues | Should -Contain 'Word' + $ValidateSetAttribute.ValidValues | Should -Contain 'HTML' + $ValidateSetAttribute.ValidValues | Should -Contain 'Text' + } + + It 'Orientation parameter should accept Portrait and Landscape' { + $OrientationParam = $Command.Parameters['Orientation'] + $ValidateSetAttribute = $OrientationParam.Attributes | Where-Object { $_ -is [System.Management.Automation.ValidateSetAttribute] } + $ValidateSetAttribute.ValidValues | Should -Contain 'Portrait' + $ValidateSetAttribute.ValidValues | Should -Contain 'Landscape' + } + + It 'Orientation parameter should have default value of Portrait' { + # Default values are set in the param block, not as attributes + # We can verify this by checking the AST or by testing the actual behavior + # For now, we'll check that the parameter exists and has the correct ValidateSet + $OrientationParam = $Command.Parameters['Orientation'] + $OrientationParam | Should -Not -BeNullOrEmpty + } + + It 'Target parameter should accept array of strings' { + $TargetParam = $Command.Parameters['Target'] + $TargetParam.ParameterType.Name | Should -Be 'String[]' + } + + It 'Should have Timestamp parameter' { + $Command.Parameters.Keys | Should -Contain 'Timestamp' + } + + It 'Should have EnableHealthCheck parameter' { + $Command.Parameters.Keys | Should -Contain 'EnableHealthCheck' + } + + It 'Should have SendEmail parameter' { + $Command.Parameters.Keys | Should -Contain 'SendEmail' + } + + It 'Should have ReportLanguage parameter' { + $Command.Parameters.Keys | Should -Contain 'ReportLanguage' + } + + It 'Should have StyleFilePath parameter' { + $Command.Parameters.Keys | Should -Contain 'StyleFilePath' + } + + It 'Should have ReportConfigFilePath parameter' { + $Command.Parameters.Keys | Should -Contain 'ReportConfigFilePath' + } + + It 'Should have AsBuiltConfigFilePath parameter' { + $Command.Parameters.Keys | Should -Contain 'AsBuiltConfigFilePath' + } + } + + Context 'Parameter Aliases' { + BeforeAll { + $Command = Get-Command -Name 'New-AsBuiltReport' + } + + It 'Target parameter should have Cluster, Server, and IP aliases' { + $TargetParam = $Command.Parameters['Target'] + $TargetParam.Aliases | Should -Contain 'Cluster' + $TargetParam.Aliases | Should -Contain 'Server' + $TargetParam.Aliases | Should -Contain 'IP' + } + + It 'OutputFolderPath parameter should have OutputPath alias' { + $OutputParam = $Command.Parameters['OutputFolderPath'] + $OutputParam.Aliases | Should -Contain 'OutputPath' + } + + It 'StyleFilePath parameter should have StylePath alias' { + $StyleParam = $Command.Parameters['StyleFilePath'] + $StyleParam.Aliases | Should -Contain 'StylePath' + } + + It 'ReportConfigFilePath parameter should have ReportConfigPath alias' { + $ReportConfigParam = $Command.Parameters['ReportConfigFilePath'] + $ReportConfigParam.Aliases | Should -Contain 'ReportConfigPath' + } + + It 'AsBuiltConfigFilePath parameter should have AsBuiltConfigPath alias' { + $AsBuiltConfigParam = $Command.Parameters['AsBuiltConfigFilePath'] + $AsBuiltConfigParam.Aliases | Should -Contain 'AsBuiltConfigPath' + } + + It 'UseInteractiveAuth parameter should have MFA alias' { + $InteractiveAuthParam = $Command.Parameters['UseInteractiveAuth'] + $InteractiveAuthParam.Aliases | Should -Contain 'MFA' + } + } + + Context 'Help Documentation' { + BeforeAll { + $Help = Get-Help -Name 'New-AsBuiltReport' -Full + } + + It 'Should have a synopsis' { + $Help.Synopsis | Should -Not -BeNullOrEmpty + } + + It 'Should have a description' { + $Help.Description | Should -Not -BeNullOrEmpty + } + + It 'Should have examples' { + $Help.Examples | Should -Not -BeNullOrEmpty + $Help.Examples.Example.Count | Should -BeGreaterThan 0 + } + + It 'Should have at least 10 examples' { + $Help.Examples.Example.Count | Should -BeGreaterOrEqual 10 + } + + It 'Should have parameter descriptions' { + $Help.Parameters.Parameter.Count | Should -BeGreaterThan 0 + } + + It 'Should have links' { + $Help.relatedLinks | Should -Not -BeNullOrEmpty + } + } + + Context 'Argument Completers' { + It 'Should have argument completer registered for Report parameter' { + # Argument completers are registered via Register-ArgumentCompleter in the script file + # They are defined outside the function, so we need to check the source file + $ModuleBase = (Get-Module -Name 'AsBuiltReport.Core').ModuleBase + $ScriptPath = Join-Path -Path $ModuleBase -ChildPath 'Src\Public\New-AsBuiltReport.ps1' + $ScriptContent = Get-Content -Path $ScriptPath -Raw + $ScriptContent | Should -Match "Register-ArgumentCompleter.*'New-AsBuiltReport'.*'Report'" + } + + It 'Should have argument completer registered for ReportLanguage parameter' { + # Argument completers are registered via Register-ArgumentCompleter in the script file + # They are defined outside the function, so we need to check the source file + $ModuleBase = (Get-Module -Name 'AsBuiltReport.Core').ModuleBase + $ScriptPath = Join-Path -Path $ModuleBase -ChildPath 'Src\Public\New-AsBuiltReport.ps1' + $ScriptContent = Get-Content -Path $ScriptPath -Raw + $ScriptContent | Should -Match "Register-ArgumentCompleter.*'New-AsBuiltReport'.*'ReportLanguage'" + } + } + + Context 'Function Behavior' { + BeforeAll { + $TestDrive = [System.IO.Path]::GetTempPath() + $TestFolder = Join-Path -Path $TestDrive -ChildPath "AsBuiltReportTest_$(Get-Random)" + New-Item -Path $TestFolder -ItemType Directory -Force | Out-Null + } + + AfterAll { + if (Test-Path $TestFolder) { + Remove-Item -Path $TestFolder -Recurse -Force -ErrorAction SilentlyContinue + } + } + + It 'Should throw error when OutputFolderPath does not exist' { + $NonExistentPath = Join-Path -Path $TestDrive -ChildPath "NonExistent_$(Get-Random)" + { New-AsBuiltReport -Report 'Test.Report' -Target '127.0.0.1' -Username 'test' -Password 'test' -OutputFolderPath $NonExistentPath -ErrorAction Stop } | Should -Throw + } + + It 'Should have proper error handling for invalid report types' { + { New-AsBuiltReport -Report 'Invalid.Report.Module' -Target '127.0.0.1' -Username 'test' -Password 'test' -OutputFolderPath $TestFolder -ErrorAction Stop } | Should -Throw + } + + It 'Should throw error when AsBuiltConfigFilePath does not exist' { + $NonExistentConfig = Join-Path -Path $TestDrive -ChildPath "NonExistent_$(Get-Random).json" + { New-AsBuiltReport -Report 'Test.Report' -Target '127.0.0.1' -Username 'test' -Password 'test' -OutputFolderPath $TestFolder -AsBuiltConfigFilePath $NonExistentConfig -ErrorAction Stop } | Should -Throw + } + } +} + +AfterAll { + Remove-Module -Name 'AsBuiltReport.Core' -Force -ErrorAction SilentlyContinue +} diff --git a/Tests/Unit/New-AsBuiltReportConfig.Tests.ps1 b/Tests/Unit/New-AsBuiltReportConfig.Tests.ps1 new file mode 100644 index 0000000..dcfea87 --- /dev/null +++ b/Tests/Unit/New-AsBuiltReportConfig.Tests.ps1 @@ -0,0 +1,132 @@ +BeforeAll { + # Import the module + $ModulePath = Join-Path -Path $PSScriptRoot -ChildPath '..\..\AsBuiltReport.Core\AsBuiltReport.Core.psd1' + Import-Module $ModulePath -Force +} + +Describe 'New-AsBuiltReportConfig Unit Tests' { + Context 'Parameter Validation' { + BeforeAll { + $Command = Get-Command -Name 'New-AsBuiltReportConfig' + } + + It 'Should have Report parameter as mandatory' { + $ReportParam = $Command.Parameters['Report'] + ($ReportParam.Attributes | Where-Object { $_ -is [System.Management.Automation.ParameterAttribute] }).Mandatory | Should -Contain $true + } + + It 'Should have FolderPath parameter as mandatory' { + $FolderPathParam = $Command.Parameters['FolderPath'] + ($FolderPathParam.Attributes | Where-Object { $_ -is [System.Management.Automation.ParameterAttribute] }).Mandatory | Should -Contain $true + } + + It 'Should have Filename parameter as optional' { + $FilenameParam = $Command.Parameters['Filename'] + $MandatoryAttributes = ($FilenameParam.Attributes | Where-Object { $_ -is [System.Management.Automation.ParameterAttribute] }).Mandatory + $MandatoryAttributes | Should -Not -Contain $true + } + + It 'Should have Force parameter' { + $Command.Parameters.Keys | Should -Contain 'Force' + } + + It 'Force parameter should be a switch' { + $ForceParam = $Command.Parameters['Force'] + $ForceParam.ParameterType.Name | Should -Be 'SwitchParameter' + } + + It 'Should have Path alias for FolderPath' { + $FolderPathParam = $Command.Parameters['FolderPath'] + $FolderPathParam.Aliases | Should -Contain 'Path' + } + + It 'Should have Name alias for Filename' { + $FilenameParam = $Command.Parameters['Filename'] + $FilenameParam.Aliases | Should -Contain 'Name' + } + + It 'Should have Overwrite alias for Force' { + $ForceParam = $Command.Parameters['Force'] + $ForceParam.Aliases | Should -Contain 'Overwrite' + } + } + + Context 'Function Behavior' { + BeforeAll { + # Create a temporary test directory + $TestDrive = [System.IO.Path]::GetTempPath() + $TestFolder = Join-Path -Path $TestDrive -ChildPath "AsBuiltReportTest_$(Get-Random)" + New-Item -Path $TestFolder -ItemType Directory -Force | Out-Null + } + + AfterAll { + # Clean up test directory + if (Test-Path $TestFolder) { + Remove-Item -Path $TestFolder -Recurse -Force -ErrorAction SilentlyContinue + } + } + + It 'Should throw error when FolderPath does not exist' { + $NonExistentPath = Join-Path -Path $TestDrive -ChildPath "NonExistent_$(Get-Random)" + { New-AsBuiltReportConfig -Report 'Test.Report' -FolderPath $NonExistentPath -ErrorAction Stop } | Should -Throw + } + + It 'Should have proper error handling for invalid report types' { + { New-AsBuiltReportConfig -Report 'Invalid.Report.Module' -FolderPath $TestFolder -ErrorAction Stop } | Should -Throw + } + } + + Context 'Help Documentation' { + BeforeAll { + $Help = Get-Help -Name 'New-AsBuiltReportConfig' -Full + } + + It 'Should have a synopsis' { + $Help.Synopsis | Should -Not -BeNullOrEmpty + } + + It 'Should have a description' { + $Help.Description | Should -Not -BeNullOrEmpty + } + + It 'Should have examples' { + $Help.Examples | Should -Not -BeNullOrEmpty + $Help.Examples.Example.Count | Should -BeGreaterThan 0 + } + + It 'Should have parameter descriptions for Report' { + ($Help.Parameters.Parameter | Where-Object { $_.Name -eq 'Report' }).Description | Should -Not -BeNullOrEmpty + } + + It 'Should have parameter descriptions for FolderPath' { + ($Help.Parameters.Parameter | Where-Object { $_.Name -eq 'FolderPath' }).Description | Should -Not -BeNullOrEmpty + } + + It 'Should have parameter descriptions for Filename' { + ($Help.Parameters.Parameter | Where-Object { $_.Name -eq 'Filename' }).Description | Should -Not -BeNullOrEmpty + } + + It 'Should have parameter descriptions for Force' { + ($Help.Parameters.Parameter | Where-Object { $_.Name -eq 'Force' }).Description | Should -Not -BeNullOrEmpty + } + + It 'Should have links' { + $Help.relatedLinks | Should -Not -BeNullOrEmpty + } + } + + Context 'Argument Completer' { + It 'Should have argument completer registered for Report parameter' { + # Argument completers are registered via Register-ArgumentCompleter in the script file + # They are defined outside the function, so we need to check the source file + $ModuleBase = (Get-Module -Name 'AsBuiltReport.Core').ModuleBase + $ScriptPath = Join-Path -Path $ModuleBase -ChildPath 'Src\Public\New-AsBuiltReportConfig.ps1' + $ScriptContent = Get-Content -Path $ScriptPath -Raw + $ScriptContent | Should -Match "Register-ArgumentCompleter.*'New-AsBuiltReportConfig'.*'Report'" + } + } +} + +AfterAll { + Remove-Module -Name 'AsBuiltReport.Core' -Force -ErrorAction SilentlyContinue +} diff --git a/Tests/Unit/Resolve-Culture.Tests.ps1 b/Tests/Unit/Resolve-Culture.Tests.ps1 new file mode 100644 index 0000000..d98d9f3 --- /dev/null +++ b/Tests/Unit/Resolve-Culture.Tests.ps1 @@ -0,0 +1,262 @@ +BeforeAll { + # Import the module + $ModulePath = Join-Path -Path $PSScriptRoot -ChildPath '..\..\AsBuiltReport.Core\AsBuiltReport.Core.psd1' + Import-Module $ModulePath -Force +} + +Describe 'Resolve-Culture Unit Tests' { + Context 'Function Exists' { + It 'Should have Resolve-Culture function available' { + InModuleScope 'AsBuiltReport.Core' { + $Function = Get-Command -Name 'Resolve-Culture' -ErrorAction SilentlyContinue + $Function | Should -Not -BeNullOrEmpty + } + } + } + + Context 'English Culture Variants' { + It 'Should resolve en-US to itself' { + InModuleScope 'AsBuiltReport.Core' { + $Result = Resolve-Culture -CultureName 'en-US' + $Result | Should -Be @('en-US') + } + } + + It 'Should resolve en-GB to en-GB, en-US' { + InModuleScope 'AsBuiltReport.Core' { + $Result = Resolve-Culture -CultureName 'en-GB' + $Result | Should -Be @('en-GB', 'en-US') + } + } + + It 'Should resolve en-AU to en-AU, en-GB, en-US' { + InModuleScope 'AsBuiltReport.Core' { + $Result = Resolve-Culture -CultureName 'en-AU' + $Result | Should -Be @('en-AU', 'en-GB', 'en-US') + } + } + + It 'Should resolve en-CA to en-CA, en-GB, en-US' { + InModuleScope 'AsBuiltReport.Core' { + $Result = Resolve-Culture -CultureName 'en-CA' + $Result | Should -Be @('en-CA', 'en-GB', 'en-US') + } + } + + It 'Should resolve en-NZ to en-NZ, en-GB, en-US' { + InModuleScope 'AsBuiltReport.Core' { + $Result = Resolve-Culture -CultureName 'en-NZ' + $Result | Should -Be @('en-NZ', 'en-GB', 'en-US') + } + } + } + + Context 'Chinese Culture Variants' { + It 'Should resolve zh-CN (Simplified Chinese) correctly' { + InModuleScope 'AsBuiltReport.Core' { + $Result = Resolve-Culture -CultureName 'zh-CN' + $Result | Should -Be @('zh-CN', 'zh-Hans', 'en-US') + } + } + + It 'Should resolve zh-TW (Traditional Chinese) correctly' { + InModuleScope 'AsBuiltReport.Core' { + $Result = Resolve-Culture -CultureName 'zh-TW' + $Result | Should -Be @('zh-TW', 'zh-Hant', 'en-US') + } + } + + It 'Should resolve zh-HK (Hong Kong) correctly' { + InModuleScope 'AsBuiltReport.Core' { + $Result = Resolve-Culture -CultureName 'zh-HK' + $Result | Should -Be @('zh-HK', 'zh-Hant', 'zh-TW', 'en-US') + } + } + + It 'Should resolve zh-Hans (Simplified) correctly' { + InModuleScope 'AsBuiltReport.Core' { + $Result = Resolve-Culture -CultureName 'zh-Hans' + $Result | Should -Be @('zh-Hans', 'zh-CN', 'en-US') + } + } + } + + Context 'French Culture Variants' { + It 'Should resolve fr-FR to fr-FR, en-US' { + InModuleScope 'AsBuiltReport.Core' { + $Result = Resolve-Culture -CultureName 'fr-FR' + $Result | Should -Be @('fr-FR', 'en-US') + } + } + + It 'Should resolve fr-CA to fr-CA, fr-FR, en-US' { + InModuleScope 'AsBuiltReport.Core' { + $Result = Resolve-Culture -CultureName 'fr-CA' + $Result | Should -Be @('fr-CA', 'fr-FR', 'en-US') + } + } + + It 'Should resolve fr-BE to fr-BE, fr-FR, en-US' { + InModuleScope 'AsBuiltReport.Core' { + $Result = Resolve-Culture -CultureName 'fr-BE' + $Result | Should -Be @('fr-BE', 'fr-FR', 'en-US') + } + } + } + + Context 'Spanish Culture Variants' { + It 'Should resolve es-ES to es-ES, en-US' { + InModuleScope 'AsBuiltReport.Core' { + $Result = Resolve-Culture -CultureName 'es-ES' + $Result | Should -Be @('es-ES', 'en-US') + } + } + + It 'Should resolve es-MX to es-MX, es-ES, en-US' { + InModuleScope 'AsBuiltReport.Core' { + $Result = Resolve-Culture -CultureName 'es-MX' + $Result | Should -Be @('es-MX', 'es-ES', 'en-US') + } + } + + It 'Should resolve es-AR to es-AR, es-ES, en-US' { + InModuleScope 'AsBuiltReport.Core' { + $Result = Resolve-Culture -CultureName 'es-AR' + $Result | Should -Be @('es-AR', 'es-ES', 'en-US') + } + } + + It 'Should resolve es-US to es-US, es-MX, es-ES, en-US' { + InModuleScope 'AsBuiltReport.Core' { + $Result = Resolve-Culture -CultureName 'es-US' + $Result | Should -Be @('es-US', 'es-MX', 'es-ES', 'en-US') + } + } + } + + Context 'German Culture Variants' { + It 'Should resolve de-DE to de-DE, en-US' { + InModuleScope 'AsBuiltReport.Core' { + $Result = Resolve-Culture -CultureName 'de-DE' + $Result | Should -Be @('de-DE', 'en-US') + } + } + + It 'Should resolve de-AT to de-AT, de-DE, en-US' { + InModuleScope 'AsBuiltReport.Core' { + $Result = Resolve-Culture -CultureName 'de-AT' + $Result | Should -Be @('de-AT', 'de-DE', 'en-US') + } + } + + It 'Should resolve de-CH to de-CH, de-DE, en-US' { + InModuleScope 'AsBuiltReport.Core' { + $Result = Resolve-Culture -CultureName 'de-CH' + $Result | Should -Be @('de-CH', 'de-DE', 'en-US') + } + } + } + + Context 'Other Major Languages' { + It 'Should resolve ja-JP to ja-JP, en-US' { + InModuleScope 'AsBuiltReport.Core' { + $Result = Resolve-Culture -CultureName 'ja-JP' + $Result | Should -Be @('ja-JP', 'en-US') + } + } + + It 'Should resolve ko-KR to ko-KR, en-US' { + InModuleScope 'AsBuiltReport.Core' { + $Result = Resolve-Culture -CultureName 'ko-KR' + $Result | Should -Be @('ko-KR', 'en-US') + } + } + + It 'Should resolve pt-BR to pt-BR, pt-PT, en-US' { + InModuleScope 'AsBuiltReport.Core' { + $Result = Resolve-Culture -CultureName 'pt-BR' + $Result | Should -Be @('pt-BR', 'pt-PT', 'en-US') + } + } + + It 'Should resolve ru-RU to ru-RU, en-US' { + InModuleScope 'AsBuiltReport.Core' { + $Result = Resolve-Culture -CultureName 'ru-RU' + $Result | Should -Be @('ru-RU', 'en-US') + } + } + + It 'Should resolve ar-SA to ar-SA, en-US' { + InModuleScope 'AsBuiltReport.Core' { + $Result = Resolve-Culture -CultureName 'ar-SA' + $Result | Should -Be @('ar-SA', 'en-US') + } + } + } + + Context 'Language Family Fallback' { + It 'Should fallback unmapped French variant to fr-FR' { + InModuleScope 'AsBuiltReport.Core' { + $Result = Resolve-Culture -CultureName 'fr-XX' + $Result | Should -Be @('fr-XX', 'fr-FR', 'en-US') + } + } + + It 'Should fallback unmapped German variant to de-DE' { + InModuleScope 'AsBuiltReport.Core' { + $Result = Resolve-Culture -CultureName 'de-XX' + $Result | Should -Be @('de-XX', 'de-DE', 'en-US') + } + } + + It 'Should fallback unmapped Spanish variant to es-ES' { + InModuleScope 'AsBuiltReport.Core' { + $Result = Resolve-Culture -CultureName 'es-XX' + $Result | Should -Be @('es-XX', 'es-ES', 'en-US') + } + } + } + + Context 'Unknown Culture Fallback' { + It 'Should fallback completely unknown culture to en-US' { + InModuleScope 'AsBuiltReport.Core' { + $Result = Resolve-Culture -CultureName 'xx-YY' + $Result | Should -Be @('xx-YY', 'en-US') + } + } + + It 'Should fallback unknown language family to en-US' { + InModuleScope 'AsBuiltReport.Core' { + $Result = Resolve-Culture -CultureName 'zz-ZZ' + $Result | Should -Be @('zz-ZZ', 'en-US') + } + } + } + + Context 'Return Type' { + It 'Should return an array' { + InModuleScope 'AsBuiltReport.Core' { + $Result = Resolve-Culture -CultureName 'en-GB' + $Result.Count | Should -BeGreaterThan 1 + } + } + + It 'Should return at least 1 culture' { + InModuleScope 'AsBuiltReport.Core' { + $Result = Resolve-Culture -CultureName 'en-US' + $Result.Count | Should -BeGreaterOrEqual 1 + } + } + + It 'Should always end with en-US fallback' { + InModuleScope 'AsBuiltReport.Core' { + $Result = Resolve-Culture -CultureName 'fr-CA' + $Result[-1] | Should -Be 'en-US' + } + } + } +} + +AfterAll { + Remove-Module -Name 'AsBuiltReport.Core' -Force -ErrorAction SilentlyContinue +} diff --git a/Tests/Unit/Write-ReportModuleInfo.Tests.ps1 b/Tests/Unit/Write-ReportModuleInfo.Tests.ps1 new file mode 100644 index 0000000..3ac932b --- /dev/null +++ b/Tests/Unit/Write-ReportModuleInfo.Tests.ps1 @@ -0,0 +1,119 @@ +BeforeAll { + # Import the module + $ModulePath = Join-Path -Path $PSScriptRoot -ChildPath '..\..\AsBuiltReport.Core\AsBuiltReport.Core.psd1' + Import-Module $ModulePath -Force + + # Ensure PowerShellGet is imported for Find-Module + Import-Module PowerShellGet -Force -ErrorAction SilentlyContinue +} + +Describe 'Write-ReportModuleInfo Unit Tests' { + Context 'Function Exists' { + It 'Should have Write-ReportModuleInfo function available' { + InModuleScope 'AsBuiltReport.Core' { + $Function = Get-Command -Name 'Write-ReportModuleInfo' -ErrorAction SilentlyContinue + $Function | Should -Not -BeNullOrEmpty + } + } + + It 'Should be a CmdletBinding function' { + InModuleScope 'AsBuiltReport.Core' { + $Function = Get-Command -Name 'Write-ReportModuleInfo' + $Function.CmdletBinding | Should -Be $true + } + } + } + + Context 'Parameter Validation' { + It 'Should have ModuleName parameter' { + InModuleScope 'AsBuiltReport.Core' { + $Command = Get-Command -Name 'Write-ReportModuleInfo' + $Command.Parameters.Keys | Should -Contain 'ModuleName' + } + } + + It 'Should have ModuleName as mandatory parameter' { + InModuleScope 'AsBuiltReport.Core' { + $Command = Get-Command -Name 'Write-ReportModuleInfo' + $Parameter = $Command.Parameters['ModuleName'] + $Parameter.Attributes.Mandatory | Should -Contain $true + } + } + } + + Context 'Basic Functionality' { + It 'Should execute without errors in non-verbose mode' { + InModuleScope 'AsBuiltReport.Core' { + Mock Get-Module { } + Mock Find-Module { } + Mock Write-Host { } + Mock Write-PScriboMessage { } + + $script:VerbosePreference = 'SilentlyContinue' + $global:translate = @{ + ReportModuleInfo1 = 'Documentation for {0} report module' + ReportModuleInfo2 = 'https://github.com/AsBuiltReport/AsBuiltReport.{0}' + ReportModuleInfo3 = 'For more information visit' + ProjectWebsite = 'https://www.asbuiltreport.com' + CommunityProject = 'AsBuiltReport is a community project' + } + + { Write-ReportModuleInfo -ModuleName 'TestModule' } | Should -Not -Throw + } + } + + It 'Should check for installed module version' { + InModuleScope 'AsBuiltReport.Core' { + Mock Get-Module { } + Mock Find-Module { } + Mock Write-Host { } + Mock Write-PScriboMessage { } + + $script:VerbosePreference = 'SilentlyContinue' + $global:translate = @{ + ReportModuleInfo1 = 'Documentation for {0} report module' + ReportModuleInfo2 = 'https://github.com/AsBuiltReport/AsBuiltReport.{0}' + ReportModuleInfo3 = 'For more information visit' + ProjectWebsite = 'https://www.asbuiltreport.com' + CommunityProject = 'AsBuiltReport is a community project' + } + + Write-ReportModuleInfo -ModuleName 'TestModule' + + Should -Invoke Get-Module -ParameterFilter { + $Name -eq 'AsBuiltReport.TestModule' -and $ListAvailable -eq $true + } + } + } + + It 'Should construct full module name correctly' { + InModuleScope 'AsBuiltReport.Core' { + Mock Get-Module { } + Mock Find-Module { } + Mock Write-Host { } + Mock Write-PScriboMessage { } + + $script:VerbosePreference = 'SilentlyContinue' + $global:translate = @{ + ReportModuleInfo1 = 'Documentation for {0} report module' + ReportModuleInfo2 = 'https://github.com/AsBuiltReport/AsBuiltReport.{0}' + ReportModuleInfo3 = 'For more information visit' + ProjectWebsite = 'https://www.asbuiltreport.com' + CommunityProject = 'AsBuiltReport is a community project' + } + + Write-ReportModuleInfo -ModuleName 'VMware.vSphere' + + Should -Invoke Get-Module -ParameterFilter { + $Name -eq 'AsBuiltReport.VMware.vSphere' + } + } + } + } +} + +AfterAll { + Remove-Module -Name 'AsBuiltReport.Core' -Force -ErrorAction SilentlyContinue + Remove-Variable -Name 'translate' -Scope Global -ErrorAction SilentlyContinue + $global:VerbosePreference = 'SilentlyContinue' +}